Initial commit: The Old Fitz Public House site
Static-turned-PHP site for a pub in Marion, Indiana, with: - Hero section with tiled brick-texture background - Live-capable stat card (Facebook followers/reviews via Graph API, with graceful fallback to config.php constants when no token is set) - Open Graph / Twitter Card meta tags for social sharing - robots.txt config.php is gitignored (holds a Facebook Page Access Token once generated); config.sample.php is the tracked template — copy it to config.php and fill in values to run this locally or in deployment.
This commit is contained in:
commit
48e26d671d
11 files changed
+883
No files matched your search
+14
@@ -0,0 +1,14 @@
|
||||
# OS cruft
|
||||
.DS_Store
|
||||
|
||||
# Secrets — copy config.sample.php to config.php and fill in your own values.
|
||||
# config.php will eventually hold a real Facebook Page Access Token.
|
||||
config.php
|
||||
|
||||
# Runtime-generated cache (facebook-stats.php writes here)
|
||||
/cache/
|
||||
|
||||
# Original raw video footage, 27MB, not referenced anywhere on the live
|
||||
# site (hero background ended up using assets/brick-texture.png instead).
|
||||
# Remove this line if you want the raw footage tracked in git too.
|
||||
assets/video.mp4
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 668 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 241 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Site config. KEEP THIS FILE PRIVATE — if this project ever goes under
|
||||
* git, add config.php to .gitignore before committing anything, since
|
||||
* FB_PAGE_ACCESS_TOKEN is a secret.
|
||||
*/
|
||||
|
||||
// Base URL the site is currently reachable at. Used for social sharing
|
||||
// meta tags (og:url, og:image, twitter:image), which need absolute URLs.
|
||||
// Currently pointed at the temporary daviddyer.me subdomain — update
|
||||
// this to the permanent domain once the site moves there.
|
||||
define('SITE_URL', 'https://theoldfitz.daviddyer.me');
|
||||
|
||||
// The Old Fitz's Facebook Page ID (from the facebook.com/profile.php?id=... links already on the site).
|
||||
define('FB_PAGE_ID', '100086635646712');
|
||||
|
||||
// Paste a Page Access Token here to make the homepage stats live.
|
||||
// Until this is filled in, the site quietly uses the fallback numbers below.
|
||||
//
|
||||
// To generate one:
|
||||
// 1. Go to https://developers.facebook.com/apps and create an app
|
||||
// (type: "Business"), logged in as an admin of The Old Fitz Page.
|
||||
// 2. In Graph API Explorer (developers.facebook.com/tools/explorer),
|
||||
// pick that app, select "Page Access Token" for The Old Fitz,
|
||||
// requesting the pages_read_engagement permission.
|
||||
// 3. Use the "Access Token Debugger" (developers.facebook.com/tools/debug/accesstoken)
|
||||
// to extend it to a long-lived token (~60 days). Long-lived Page
|
||||
// tokens generally don't expire on their own with regular use, but
|
||||
// Meta can still invalidate one (password change, permission
|
||||
// changes, app review) — if that happens, this just falls back to
|
||||
// the numbers below instead of breaking the page.
|
||||
define('FB_PAGE_ACCESS_TOKEN', '');
|
||||
|
||||
// How often to re-fetch from Facebook, in seconds. 6 hours is plenty for
|
||||
// numbers that move a few times a month.
|
||||
define('FB_STATS_CACHE_TTL', 6 * 60 * 60);
|
||||
|
||||
// Fallback numbers — used whenever there's no token yet, or the Facebook
|
||||
// API call fails for any reason. Update these by hand if you're not
|
||||
// using the live token.
|
||||
define('FB_FALLBACK_RECOMMEND_PCT', 92);
|
||||
define('FB_FALLBACK_REVIEW_COUNT', 11);
|
||||
define('FB_FALLBACK_FOLLOWERS', 2600);
|
||||
@@ -0,0 +1,45 @@
|
||||
name: the-old-fitz
|
||||
|
||||
networks:
|
||||
nginxproxymanager:
|
||||
name: nginxproxymanager
|
||||
external: true
|
||||
|
||||
services:
|
||||
php-server:
|
||||
image: php:8.3-apache
|
||||
container_name: the-old-fitz
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- nginxproxymanager
|
||||
volumes:
|
||||
- type: bind
|
||||
source: /DATA/AppData/theoldfitz/www
|
||||
target: /var/www/html
|
||||
environment:
|
||||
- TZ=America/Indiana/Indianapolis
|
||||
labels:
|
||||
icon: https://www.php.net/images/logos/php-logo.svg
|
||||
|
||||
x-casaos:
|
||||
architectures:
|
||||
- amd64
|
||||
- arm64
|
||||
author: self
|
||||
category: Developer
|
||||
description:
|
||||
en_us: PHP web server running Apache, proxied through Nginx Proxy Manager.
|
||||
developer: PHP
|
||||
hostname: theoldfitz.daviddyer.me
|
||||
icon: https://www.php.net/images/logos/php-logo.svg
|
||||
id: self.php-server
|
||||
index: /
|
||||
is_uncontrolled: false
|
||||
main: php-server
|
||||
port_map: "80"
|
||||
scheme: http
|
||||
tagline:
|
||||
en_us: PHP 8.3 + Apache web server.
|
||||
thumbnail: https://www.php.net/images/logos/php-logo.svg
|
||||
title:
|
||||
en_us: PHP Server
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Pulls "recommend %", review count, and follower count from The Old
|
||||
* Fitz's Facebook Page via the Graph API, cached to a local JSON file so
|
||||
* we don't hit Facebook on every page load. Falls back to the numbers in
|
||||
* config.php whenever there's no access token yet, or the API call fails
|
||||
* for any reason — the homepage never breaks because of this.
|
||||
*
|
||||
* Known limitation: Facebook's newer thumbs-up/down "recommendation"
|
||||
* system (the "X% recommend (Y reviews)" wording used on the Page today)
|
||||
* doesn't have a confirmed, stable Graph API field the way star ratings
|
||||
* do. This code requests overall_star_rating/rating_count and converts
|
||||
* a star rating to a percentage if Facebook returns one; if the Page's
|
||||
* review data isn't exposed that way, recommend_pct/review_count will
|
||||
* silently stay at the config.php fallback while followers_count still
|
||||
* goes live. That's expected, not a bug — Meta's review-related API
|
||||
* access has gotten more restricted over time.
|
||||
*/
|
||||
|
||||
function fritz_facebook_stats(): array {
|
||||
$fallback = [
|
||||
'recommend_pct' => FB_FALLBACK_RECOMMEND_PCT,
|
||||
'review_count' => FB_FALLBACK_REVIEW_COUNT,
|
||||
'followers' => FB_FALLBACK_FOLLOWERS,
|
||||
'source' => 'fallback',
|
||||
'fetched_at' => null,
|
||||
];
|
||||
|
||||
if (FB_PAGE_ACCESS_TOKEN === '') {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
$cacheFile = __DIR__ . '/../cache/facebook-stats.json';
|
||||
|
||||
if (is_file($cacheFile)) {
|
||||
$cached = json_decode((string) file_get_contents($cacheFile), true);
|
||||
if (is_array($cached) && (time() - ($cached['fetched_at'] ?? 0)) < FB_STATS_CACHE_TTL) {
|
||||
$cached['source'] = 'cache';
|
||||
return $cached;
|
||||
}
|
||||
}
|
||||
|
||||
$fresh = fritz_fetch_facebook_stats($fallback);
|
||||
$fresh['fetched_at'] = time();
|
||||
|
||||
$cacheDir = dirname($cacheFile);
|
||||
if (!is_dir($cacheDir)) {
|
||||
@mkdir($cacheDir, 0775, true);
|
||||
}
|
||||
@file_put_contents($cacheFile, json_encode($fresh));
|
||||
|
||||
return $fresh;
|
||||
}
|
||||
|
||||
function fritz_fetch_facebook_stats(array $fallback): array {
|
||||
if (!function_exists('curl_init')) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
$url = sprintf(
|
||||
'https://graph.facebook.com/v21.0/%s?fields=followers_count,overall_star_rating,rating_count&access_token=%s',
|
||||
FB_PAGE_ID,
|
||||
urlencode(FB_PAGE_ACCESS_TOKEN)
|
||||
);
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 5,
|
||||
]);
|
||||
$body = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($body === false || $httpCode !== 200) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
$data = json_decode($body, true);
|
||||
if (!is_array($data) || isset($data['error'])) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
$recommendPct = isset($data['overall_star_rating'])
|
||||
? (int) round(($data['overall_star_rating'] / 5) * 100)
|
||||
: $fallback['recommend_pct'];
|
||||
|
||||
return [
|
||||
'recommend_pct' => $recommendPct,
|
||||
'review_count' => $data['rating_count'] ?? $fallback['review_count'],
|
||||
'followers' => $data['followers_count'] ?? $fallback['followers'],
|
||||
'source' => 'live',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
require __DIR__ . '/config.php';
|
||||
require __DIR__ . '/inc/facebook-stats.php';
|
||||
$fbStats = fritz_facebook_stats();
|
||||
$siteUrl = rtrim(SITE_URL, '/');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>The Old Fitz Public House | Traditional Irish Pub in Marion, Indiana</title>
|
||||
<meta name="description" content="The Old Fitz Public House — a traditional Irish pub in Marion, Indiana. Open Thursday through Saturday, 4–10pm. Family friendly, no reservations.">
|
||||
<link rel="canonical" href="https://theoldfitz.daviddyer.me">
|
||||
|
||||
<!-- Social sharing (Open Graph / Twitter Card) -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="The Old Fitz Public House">
|
||||
<meta property="og:title" content="The Old Fitz Public House | Traditional Irish Pub in Marion, Indiana">
|
||||
<meta property="og:description" content="A traditional Irish pub in Marion, Indiana. Open Thursday through Saturday, 4–10pm. Family friendly, no reservations.">
|
||||
<meta property="og:url" content="<?= $siteUrl ?>/">
|
||||
<meta property="og:image" content="<?= $siteUrl ?>/assets/og-image.png">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:image:alt" content="The Old Fitz Public House">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="The Old Fitz Public House | Traditional Irish Pub in Marion, Indiana">
|
||||
<meta name="twitter:description" content="A traditional Irish pub in Marion, Indiana. Open Thursday through Saturday, 4–10pm. Family friendly, no reservations.">
|
||||
<meta name="twitter:image" content="<?= $siteUrl ?>/assets/og-image.png">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,400;0,9..144,500;0,9..144,600;0,9..144,700;1,9..144,400;1,9..144,500&family=Karla:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
|
||||
<header class="site">
|
||||
<div class="container nav-inner">
|
||||
<a class="brand" href="#main">
|
||||
<img class="knot" src="./assets/knot.png" alt="">
|
||||
<span>THE OLD FITZ</span>
|
||||
</a>
|
||||
<nav class="links" aria-label="Primary">
|
||||
<a href="#about">About</a>
|
||||
<a href="#visit">Hours & Visit</a>
|
||||
<a href="#music">Live Music</a>
|
||||
<a href="#menu">Menu</a>
|
||||
<a href="#contact">Contact</a>
|
||||
</nav>
|
||||
<a class="nav-cta" href="https://www.google.com/maps/search/?api=1&query=100+N+Washington+St+Marion+IN" target="_blank" rel="noopener">Get Directions</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
|
||||
<section class="hero">
|
||||
<div class="hero-media" aria-hidden="true">
|
||||
<div class="hero-scrim"></div>
|
||||
</div>
|
||||
<div class="container hero-inner">
|
||||
<h1 class="hero-brand">
|
||||
<img class="hero-logo" src="./assets/hero-logo.png" alt="The Old Fitz Public House">
|
||||
</h1>
|
||||
<p class="eyebrow">Marion, Indiana</p>
|
||||
<!-- <h1>The Old Fitz</h1> -->
|
||||
<!-- <p class="sub">Public House</p> -->
|
||||
<div class="tagline-row">
|
||||
<span>Traditional Irish Pub</span><span>Family Friendly</span><span>No Reservations</span>
|
||||
</div>
|
||||
<div class="hero-ctas">
|
||||
<a class="btn btn-primary" href="https://www.google.com/maps/search/?api=1&query=100+N+Washington+St+Marion+IN" target="_blank" rel="noopener">Get Directions</a>
|
||||
<a class="btn btn-outline" href="mailto:info@theoldfitzpub.com">Say Hello</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="about">
|
||||
<div class="container">
|
||||
<div class="about-grid">
|
||||
<div class="reveal">
|
||||
<p class="eyebrow">About the Pub</p>
|
||||
<h2 style="margin-top:0.6rem;">A proper Irish pub, right on Washington Street.</h2>
|
||||
<p class="lede" style="margin-top:1.5rem;">The Old Fitz Public House pours a traditional Irish pub experience in the middle of Marion — no pretense, no reservations, just a good pint and a warm room. Walk in Thursday through Saturday evening, grab a seat at the bar or a table for the family, and settle in.</p>
|
||||
<p class="lede">The kitchen runs until 9, the bar stays open later for snacks, and regulars and first-timers get treated the same.</p>
|
||||
</div>
|
||||
<div class="stat-card reveal">
|
||||
<span class="eyebrow">As the Regulars See It</span>
|
||||
<div class="stat-big"><?= (int) $fbStats['recommend_pct'] ?>%</div>
|
||||
<p class="stat-label">recommend The Old Fitz</p>
|
||||
<p class="stat-source">Source: Facebook reviews (<?= (int) $fbStats['review_count'] ?>)</p>
|
||||
<div class="stat-row">
|
||||
<div class="stat-big"><?= number_format((int) $fbStats['followers']) ?>+</div>
|
||||
<p class="stat-label">people following along on Facebook</p>
|
||||
<p class="stat-source">Source: Facebook followers</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="visit" class="visit">
|
||||
<div class="container">
|
||||
<div class="section-head reveal">
|
||||
<p class="eyebrow">Hours & Visit</p>
|
||||
<h2>Three nights a week, doors open.</h2>
|
||||
</div>
|
||||
<div class="visit-grid">
|
||||
<div class="card reveal">
|
||||
<h3>On Tap Thu–Sat</h3>
|
||||
<dl class="hours-list">
|
||||
<div class="hours-row">
|
||||
<dt>Thursday</dt>
|
||||
<dd>4:00 – 10:00 PM</dd>
|
||||
</div>
|
||||
<div class="hours-row">
|
||||
<dt>Friday</dt>
|
||||
<dd>4:00 – 10:00 PM</dd>
|
||||
</div>
|
||||
<div class="hours-row">
|
||||
<dt>Saturday</dt>
|
||||
<dd>4:00 – 10:00 PM</dd>
|
||||
</div>
|
||||
<div class="hours-row">
|
||||
<dt>Sun – Wed</dt>
|
||||
<dd>Closed</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p class="note"><strong>Kitchen closes at 9</strong> — bar snacks stay out later. Holiday hours may vary; check our Facebook page for the latest.</p>
|
||||
</div>
|
||||
<div class="card find-us reveal" id="contact">
|
||||
<svg class="pin" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||
<path d="M12 2C7.86 2 4.5 5.36 4.5 9.5c0 5.5 6.2 11.16 7.06 11.92a.7.7 0 0 0 .88 0C13.3 20.66 19.5 15 19.5 9.5 19.5 5.36 16.14 2 12 2Z" stroke="var(--gold)" stroke-width="1.4" />
|
||||
<circle cx="12" cy="9.5" r="2.6" stroke="var(--gold)" stroke-width="1.4" />
|
||||
</svg>
|
||||
<h3>Find Us</h3>
|
||||
<address>
|
||||
100 N Washington Street<br>
|
||||
Marion, Indiana
|
||||
</address>
|
||||
<div class="contact-list">
|
||||
<a href="https://www.google.com/maps/search/?api=1&query=100+N+Washington+St+Marion+IN" target="_blank" rel="noopener">Get Directions →</a>
|
||||
<a href="mailto:info@theoldfitzpub.com">info@theoldfitzpub.com</a>
|
||||
</div>
|
||||
<div class="social-row">
|
||||
<a href="https://www.instagram.com/theoldfitzpub/?hl=en" target="_blank" rel="noopener" aria-label="The Old Fitz on Instagram">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
|
||||
<rect x="3" y="3" width="18" height="18" rx="5" />
|
||||
<circle cx="12" cy="12" r="4.2" />
|
||||
<circle cx="17.2" cy="6.8" r="1" />
|
||||
</svg>
|
||||
</a>
|
||||
<a href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener" aria-label="The Old Fitz on Facebook">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
|
||||
<path d="M15 4h-2.2C10.7 4 9.5 5.3 9.5 7.3V10H7v3.2h2.5V21h3.3v-7.8h2.6l.4-3.2h-3V7.6c0-.8.4-1.3 1.4-1.3H15V4Z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="music" class="music">
|
||||
<div class="container">
|
||||
<div class="rule-row reveal"><span class="line"></span><img class="knot" src="./assets/knot.png" alt=""><span class="line"></span></div>
|
||||
<div class="section-head reveal">
|
||||
<p class="eyebrow">Live Music</p>
|
||||
<h2>Some nights, there's music.</h2>
|
||||
</div>
|
||||
<p class="body reveal">The Old Fitz brings in local musicians for live sets on select evenings — recent nights have featured artists like Casey Morris. There's no fixed weekly lineup here, so the surest way to catch a show is to follow along on Facebook or Instagram, where new dates get posted first.</p>
|
||||
<div class="hero-ctas reveal">
|
||||
<a class="btn btn-outline" href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener">Follow on Facebook</a>
|
||||
<a class="btn btn-outline" href="https://www.instagram.com/theoldfitzpub/?hl=en" target="_blank" rel="noopener">Follow on Instagram</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="menu" class="menu-band">
|
||||
<div class="container">
|
||||
<div class="rule-row reveal"><span class="line"></span><img class="knot" src="./assets/knot.png" alt=""><span class="line"></span></div>
|
||||
<div class="section-head reveal">
|
||||
<p class="eyebrow">The Menu</p>
|
||||
<h2>Pub food and a full bar, Thursday through Saturday.</h2>
|
||||
</div>
|
||||
<p class="body reveal">The current menu lives behind the bar and gets posted on our Facebook page. Stop in, or send us a message and we'll get you sorted before you arrive.</p>
|
||||
<div class="hero-ctas reveal">
|
||||
<a class="btn btn-primary" href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener">See Menu Updates on Facebook</a>
|
||||
<a class="btn btn-outline" href="mailto:info@theoldfitzpub.com">Email a Question</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="footer-grid">
|
||||
<div>
|
||||
<a class="footer-brand" href="#main">
|
||||
<img class="knot" src="./assets/knot.png" alt="">
|
||||
<span>THE OLD FITZ PUBLIC HOUSE</span>
|
||||
</a>
|
||||
<address style="margin-top:1rem;">
|
||||
100 N Washington Street<br>
|
||||
Marion, Indiana
|
||||
</address>
|
||||
</div>
|
||||
<div>
|
||||
<p class="col-title">Hours</p>
|
||||
<div class="hours-mini">
|
||||
<span>Thu — Sat · 4:00–10:00 PM</span>
|
||||
<span>Kitchen closes at 9 PM</span>
|
||||
<span>Sun — Wed · Closed</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p class="col-title">Get in Touch</p>
|
||||
<a class="email" href="mailto:info@theoldfitzpub.com">info@theoldfitzpub.com</a>
|
||||
<div class="social-row" style="margin-top:1rem;">
|
||||
<a href="https://www.instagram.com/theoldfitzpub/?hl=en" target="_blank" rel="noopener" aria-label="Instagram">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
|
||||
<rect x="3" y="3" width="18" height="18" rx="5" />
|
||||
<circle cx="12" cy="12" r="4.2" />
|
||||
<circle cx="17.2" cy="6.8" r="1" />
|
||||
</svg>
|
||||
</a>
|
||||
<a href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener" aria-label="Facebook">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
|
||||
<path d="M15 4h-2.2C10.7 4 9.5 5.3 9.5 7.3V10H7v3.2h2.5V21h3.3v-7.8h2.6l.4-3.2h-3V7.6c0-.8.4-1.3 1.4-1.3H15V4Z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<span>© 2026 The Old Fitz Public House</span>
|
||||
<span>A neighborhood pub in Marion, Indiana</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||
var els = document.querySelectorAll('.reveal');
|
||||
if (!('IntersectionObserver' in window)) { els.forEach(function(e) { e.classList.add('is-visible'); }); return; }
|
||||
var io = new IntersectionObserver(function(entries) {
|
||||
entries.forEach(function(entry) {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('is-visible');
|
||||
io.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.15 });
|
||||
els.forEach(function(e) { io.observe(e); });
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Disallow: /config.php
|
||||
Disallow: /inc/
|
||||
Disallow: /cache/
|
||||
|
||||
# Crawl-delay and request-rate (optional, helps with server load)
|
||||
Crawl-delay: 1
|
||||
|
||||
# Sitemap (optional, uncomment when you have one)
|
||||
# Sitemap: https://theoldfitz.daviddyer.me/sitemap.xml
|
||||
+410
@@ -0,0 +1,410 @@
|
||||
:root{
|
||||
--ground:#171310;
|
||||
--ground-2:#0f0c0a;
|
||||
--surface:#221c16;
|
||||
--surface-2:#2b2319;
|
||||
--gold:#c9a35c;
|
||||
--gold-bright:#e6c789;
|
||||
--gold-dim:#a68b59;
|
||||
--green:#33503f;
|
||||
--green-deep:#203026;
|
||||
--ink:#f1e8d8;
|
||||
--ink-muted:#a89a83;
|
||||
--rule:#42362590;
|
||||
}
|
||||
|
||||
*{ box-sizing:border-box; }
|
||||
html{ scroll-behavior:smooth; }
|
||||
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior:auto; } }
|
||||
|
||||
body{
|
||||
margin:0;
|
||||
background:var(--ground);
|
||||
color:var(--ink);
|
||||
font-family:'Karla', ui-sans-serif, system-ui, sans-serif;
|
||||
font-size:1rem;
|
||||
line-height:1.65;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
}
|
||||
|
||||
a{ color:inherit; }
|
||||
img,svg{ display:block; max-width:100%; }
|
||||
|
||||
.container{
|
||||
width:100%;
|
||||
max-width:70rem;
|
||||
margin:0 auto;
|
||||
padding-inline:1.5rem;
|
||||
}
|
||||
|
||||
h1,h2,h3{
|
||||
font-family:'Fraunces', Georgia, 'Times New Roman', serif;
|
||||
font-weight:600;
|
||||
line-height:1.08;
|
||||
text-wrap:balance;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.eyebrow{
|
||||
font-family:'IBM Plex Mono', ui-monospace, Menlo, monospace;
|
||||
font-size:0.72rem;
|
||||
letter-spacing:0.22em;
|
||||
text-transform:uppercase;
|
||||
color:var(--gold);
|
||||
}
|
||||
|
||||
p{ margin:0; }
|
||||
.muted{ color:var(--ink-muted); }
|
||||
|
||||
.visually-hidden{
|
||||
position:absolute; width:1px; height:1px; overflow:hidden;
|
||||
clip:rect(0 0 0 0); white-space:nowrap; border:0; padding:0; margin:-1px;
|
||||
}
|
||||
|
||||
.skip-link{
|
||||
position:absolute; left:1rem; top:-3rem;
|
||||
background:var(--gold); color:var(--ground-2);
|
||||
padding:0.6rem 1rem; border-radius:0.125rem;
|
||||
font-family:'IBM Plex Mono', monospace; font-size:0.85rem;
|
||||
transition:top .15s ease;
|
||||
z-index:100;
|
||||
}
|
||||
.skip-link:focus{ top:1rem; }
|
||||
|
||||
:focus-visible{ outline:2px solid var(--gold-bright); outline-offset:3px; }
|
||||
|
||||
/* ---------- knot mark ---------- */
|
||||
.knot{
|
||||
display:block;
|
||||
width:1.75rem; height:1.75rem;
|
||||
object-fit:contain;
|
||||
flex-shrink:0;
|
||||
}
|
||||
.rule-row .knot{ width:1.375rem; height:1.375rem; opacity:0.9; }
|
||||
.footer-brand .knot{ width:1.625rem; height:1.625rem; }
|
||||
|
||||
.hero-brand{
|
||||
margin:0;
|
||||
line-height:0;
|
||||
}
|
||||
|
||||
.hero-logo{
|
||||
display:block;
|
||||
width:min(100%, 26.25rem);
|
||||
max-width:100%;
|
||||
height:auto;
|
||||
margin:0 auto 1.75rem;
|
||||
}
|
||||
|
||||
@media (max-width: 35em){
|
||||
.hero-logo{ width:min(100%, 17.5rem); }
|
||||
}
|
||||
|
||||
/* ---------- brass rule divider ---------- */
|
||||
.rule-row{
|
||||
display:flex; align-items:center; gap:1rem;
|
||||
max-width:13.75rem; margin-inline:auto;
|
||||
}
|
||||
.rule-row .line{ height:1px; flex:1; background:linear-gradient(90deg, transparent, var(--gold-dim), transparent); }
|
||||
.rule-row.left-align{ margin-inline:0; }
|
||||
|
||||
/* ---------- header / nav ---------- */
|
||||
header.site{
|
||||
position:sticky; top:0; z-index:50;
|
||||
background:rgba(15,12,10,0.86);
|
||||
backdrop-filter:saturate(140%) blur(0.5rem);
|
||||
border-bottom:1px solid var(--rule);
|
||||
}
|
||||
.nav-inner{
|
||||
display:flex; align-items:center; justify-content:space-between;
|
||||
gap:1rem; padding-block:0.75rem;
|
||||
}
|
||||
.brand{
|
||||
display:flex; align-items:center; gap:0.65rem;
|
||||
text-decoration:none;
|
||||
font-family:'Fraunces', serif; font-weight:600;
|
||||
letter-spacing:0.02em;
|
||||
font-size:1.05rem;
|
||||
color:var(--ink);
|
||||
}
|
||||
nav.links{
|
||||
display:flex; align-items:center; gap:1.75rem;
|
||||
}
|
||||
nav.links a{
|
||||
text-decoration:none;
|
||||
font-size:0.92rem;
|
||||
letter-spacing:0.03em;
|
||||
color:var(--ink-muted);
|
||||
padding:0.4rem 0.2rem;
|
||||
transition:color .15s ease;
|
||||
}
|
||||
nav.links a:hover{ color:var(--gold-bright); }
|
||||
.nav-cta{
|
||||
display:inline-flex; align-items:center;
|
||||
border:1px solid var(--gold-dim);
|
||||
color:var(--gold-bright) !important;
|
||||
padding:0.45rem 0.9rem;
|
||||
border-radius:0.125rem;
|
||||
font-family:'IBM Plex Mono', monospace;
|
||||
font-size:0.75rem !important;
|
||||
letter-spacing:0.06em;
|
||||
}
|
||||
.nav-cta:hover{ border-color:var(--gold); background:var(--surface); }
|
||||
|
||||
@media (max-width: 47.5em){
|
||||
nav.links{ display:none; }
|
||||
}
|
||||
|
||||
/* ---------- hero ---------- */
|
||||
.hero{
|
||||
position:relative;
|
||||
padding-block:5.5rem 6rem;
|
||||
text-align:center;
|
||||
overflow:hidden;
|
||||
background:var(--ground); /* fallback if brick-texture.png fails to load */
|
||||
}
|
||||
.hero::before{
|
||||
content:"";
|
||||
position:absolute; inset:0;
|
||||
z-index:1;
|
||||
opacity:0.6;
|
||||
background:
|
||||
linear-gradient(to bottom, rgba(0,0,0,0.12), transparent 22%, transparent 78%, rgba(0,0,0,0.18));
|
||||
pointer-events:none;
|
||||
}
|
||||
.hero-media{
|
||||
position:absolute; inset:0;
|
||||
z-index:0;
|
||||
overflow:hidden;
|
||||
background-image:url('./assets/brick-texture.png');
|
||||
background-repeat:repeat;
|
||||
}
|
||||
.hero-scrim{
|
||||
position:absolute; inset:0;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(15,12,10,0.35) 0%, rgba(15,12,10,0.2) 45%, rgba(15,12,10,0.6) 100%),
|
||||
radial-gradient(ellipse 60% 48% at 50% 18%, rgba(201,163,92,0.16), transparent 58%);
|
||||
}
|
||||
.hero-inner{ position:relative; z-index:2; }
|
||||
.hero .eyebrow{ margin-bottom:1rem; }
|
||||
.hero h1{
|
||||
font-size:clamp(3.1rem, 9vw, 6.2rem);
|
||||
color:var(--gold-bright);
|
||||
letter-spacing:-0.01em;
|
||||
}
|
||||
.hero .sub{
|
||||
font-family:'Fraunces', serif; font-style:italic; font-weight:400;
|
||||
font-size:clamp(1.15rem, 2.6vw, 1.55rem);
|
||||
color:var(--ink-muted);
|
||||
margin-top:0.35rem;
|
||||
}
|
||||
.tagline-row{
|
||||
margin-top:2rem;
|
||||
display:flex; justify-content:center; flex-wrap:wrap;
|
||||
gap:0.6rem 0;
|
||||
font-family:'IBM Plex Mono', monospace;
|
||||
font-size:0.82rem;
|
||||
letter-spacing:0.04em;
|
||||
color:var(--ink-muted);
|
||||
}
|
||||
.tagline-row span:not(:last-child)::after{
|
||||
content:"·"; color:var(--gold-dim); margin-inline:0.7rem;
|
||||
}
|
||||
.hero-ctas{
|
||||
margin-top:2.5rem;
|
||||
display:flex; justify-content:center; gap:0.9rem; flex-wrap:wrap;
|
||||
}
|
||||
|
||||
.btn{
|
||||
display:inline-flex; align-items:center; gap:0.5rem;
|
||||
padding:0.8rem 1.5rem;
|
||||
font-family:'IBM Plex Mono', monospace;
|
||||
font-size:0.8rem; letter-spacing:0.05em;
|
||||
text-decoration:none;
|
||||
border-radius:0.125rem;
|
||||
transition:transform .15s ease, background .15s ease, border-color .15s ease;
|
||||
}
|
||||
.btn:hover{ transform:translateY(-1px); }
|
||||
.btn-primary{
|
||||
background:linear-gradient(180deg, var(--gold-bright), var(--gold));
|
||||
color:var(--ground-2);
|
||||
font-weight:500;
|
||||
}
|
||||
.btn-primary:hover{ background:linear-gradient(180deg, var(--gold-bright), var(--gold-bright)); }
|
||||
.btn-outline{
|
||||
border:1px solid var(--gold-dim);
|
||||
color:var(--gold-bright);
|
||||
}
|
||||
.btn-outline:hover{ border-color:var(--gold); background:var(--surface); }
|
||||
|
||||
/* ---------- sections ---------- */
|
||||
section{ padding-block:5.5rem; }
|
||||
.section-head{ margin-bottom:2.75rem; }
|
||||
.section-head h2{ font-size:clamp(1.9rem, 3.6vw, 2.6rem); color:var(--ink); margin-top:0.5rem; }
|
||||
|
||||
/* about band */
|
||||
.about-grid{
|
||||
display:grid; grid-template-columns:1.3fr 1fr; gap:3.5rem;
|
||||
align-items:start;
|
||||
}
|
||||
.about-grid p + p{ margin-top:1rem; }
|
||||
.about-grid .lede{ max-width:56ch; color:var(--ink); font-size:1.05rem; }
|
||||
|
||||
.stat-card{
|
||||
background:var(--surface);
|
||||
border:1px solid var(--rule);
|
||||
padding:2rem;
|
||||
border-radius:0.2rem;
|
||||
}
|
||||
.stat-card .eyebrow{ display:block; margin-bottom:1.1rem; }
|
||||
.stat-big{
|
||||
font-family:'Fraunces', serif; font-weight:600; font-style:italic;
|
||||
font-size:3rem; color:var(--gold-bright); line-height:1;
|
||||
}
|
||||
.stat-card .stat-label{ margin-top:0.4rem; font-size:0.92rem; color:var(--ink-muted); }
|
||||
.stat-card .stat-row{ margin-top:1.5rem; padding-top:1.5rem; border-top:1px solid var(--rule); }
|
||||
.stat-card .stat-row .stat-big{ font-size:1.9rem; }
|
||||
.stat-source{
|
||||
margin-top:1.5rem; font-family:'IBM Plex Mono', monospace; font-size:0.7rem;
|
||||
color:var(--gold-dim); letter-spacing:0.05em;
|
||||
}
|
||||
|
||||
@media (max-width: 51.25em){
|
||||
.about-grid{ grid-template-columns:1fr; }
|
||||
}
|
||||
|
||||
/* hours / visit band */
|
||||
.visit{ background:var(--ground-2); }
|
||||
.visit-grid{
|
||||
display:grid; grid-template-columns:1fr 1fr; gap:1.75rem;
|
||||
}
|
||||
.card{
|
||||
background:var(--surface);
|
||||
border:1px solid var(--rule);
|
||||
border-radius:0.2rem;
|
||||
padding:2.25rem;
|
||||
}
|
||||
.card h3{
|
||||
font-size:1.3rem; color:var(--gold-bright);
|
||||
margin-bottom:1.4rem;
|
||||
}
|
||||
.hours-list{
|
||||
margin:0;
|
||||
padding:0;
|
||||
font-family:'IBM Plex Mono', monospace;
|
||||
font-variant-numeric:tabular-nums;
|
||||
font-size:0.92rem;
|
||||
}
|
||||
.hours-row{
|
||||
display:flex;
|
||||
justify-content:space-between;
|
||||
align-items:center;
|
||||
padding:0.55rem 0;
|
||||
border-bottom:1px solid var(--rule);
|
||||
}
|
||||
.hours-row:last-child{
|
||||
border-bottom:none;
|
||||
}
|
||||
.hours-row dt{
|
||||
margin:0;
|
||||
color:var(--ink-muted);
|
||||
letter-spacing:0.04em;
|
||||
font-weight:normal;
|
||||
}
|
||||
.hours-row dd{
|
||||
margin:0;
|
||||
text-align:right;
|
||||
color:var(--ink);
|
||||
}
|
||||
.card .note{
|
||||
margin-top:1.25rem; font-size:0.88rem; color:var(--ink-muted);
|
||||
}
|
||||
.card .note strong{ color:var(--ink); font-weight:600; }
|
||||
|
||||
.find-us .pin{ width:2.125rem; height:2.125rem; margin-bottom:1rem; }
|
||||
.find-us address{ font-style:normal; font-size:1rem; color:var(--ink); }
|
||||
.find-us .contact-list{ margin-top:1.5rem; display:flex; flex-direction:column; gap:0.6rem; }
|
||||
.find-us .contact-list a{
|
||||
text-decoration:none; color:var(--gold-bright);
|
||||
font-size:0.92rem; display:inline-flex; align-items:center; gap:0.5rem;
|
||||
width:fit-content;
|
||||
border-bottom:1px solid transparent;
|
||||
}
|
||||
.find-us .contact-list a:hover{ border-bottom-color:var(--gold-dim); }
|
||||
.social-row{ margin-top:1.5rem; display:flex; gap:0.9rem; }
|
||||
.social-row a{
|
||||
display:inline-flex; align-items:center; justify-content:center;
|
||||
width:2.375rem; height:2.375rem;
|
||||
border:1px solid var(--rule); border-radius:0.125rem;
|
||||
color:var(--ink-muted);
|
||||
text-decoration:none;
|
||||
transition:border-color .15s ease, color .15s ease;
|
||||
}
|
||||
.social-row a:hover{ border-color:var(--gold); color:var(--gold-bright); }
|
||||
.social-row svg{ width:1.0625rem; height:1.0625rem; }
|
||||
|
||||
@media (max-width: 45em){
|
||||
.visit-grid{ grid-template-columns:1fr; }
|
||||
}
|
||||
|
||||
/* live music band */
|
||||
.music{
|
||||
background:linear-gradient(180deg, var(--green-deep), var(--green));
|
||||
color:var(--ink);
|
||||
text-align:center;
|
||||
}
|
||||
.music .section-head{ margin-bottom:1.75rem; }
|
||||
.music .section-head .eyebrow{ color:var(--gold-bright); }
|
||||
.music p.body{ max-width:58ch; margin:0 auto; font-size:1.02rem; color:#e4ddc9; }
|
||||
.music .btn-outline{ border-color:rgba(230,199,137,0.45); }
|
||||
.music .hero-ctas{ margin-top:2.25rem; }
|
||||
|
||||
/* menu band */
|
||||
.menu-band .container{ max-width:47.5rem; text-align:center; }
|
||||
.menu-band p.body{ font-size:1.02rem; color:var(--ink-muted); max-width:56ch; margin:0 auto; }
|
||||
.menu-band .hero-ctas{ margin-top:2.25rem; justify-content:center; }
|
||||
.menu-band .section-head{ text-align:center; }
|
||||
.menu-band .rule-row{ margin-bottom:1.75rem; }
|
||||
|
||||
/* footer */
|
||||
footer{
|
||||
background:var(--ground-2);
|
||||
border-top:1px solid var(--rule);
|
||||
padding-block:3.5rem 2.5rem;
|
||||
}
|
||||
.footer-grid{
|
||||
display:grid; grid-template-columns:1.2fr 1fr 1fr; gap:2.5rem;
|
||||
}
|
||||
.footer-brand{ display:flex; align-items:center; gap:0.6rem; text-decoration:none; }
|
||||
.footer-brand .knot{ width:1.625rem; height:1.625rem; }
|
||||
.footer-brand span{
|
||||
font-family:'Fraunces', serif; font-weight:600; color:var(--ink); font-size:1rem;
|
||||
}
|
||||
footer .col-title{
|
||||
font-family:'IBM Plex Mono', monospace; font-size:0.72rem;
|
||||
letter-spacing:0.14em; text-transform:uppercase; color:var(--gold-dim);
|
||||
margin-bottom:0.9rem;
|
||||
}
|
||||
footer address{ font-style:normal; color:var(--ink-muted); font-size:0.92rem; line-height:1.7; }
|
||||
footer .hours-mini{
|
||||
font-family:'IBM Plex Mono', monospace; font-size:0.85rem;
|
||||
color:var(--ink-muted); font-variant-numeric:tabular-nums;
|
||||
display:flex; flex-direction:column; gap:0.35rem;
|
||||
}
|
||||
footer a.email{ color:var(--gold-bright); text-decoration:none; font-size:0.92rem; }
|
||||
footer a.email:hover{ text-decoration:underline; }
|
||||
.footer-bottom{
|
||||
margin-top:3rem; padding-top:1.75rem; border-top:1px solid var(--rule);
|
||||
display:flex; justify-content:space-between; flex-wrap:wrap; gap:0.75rem;
|
||||
font-size:0.78rem; color:var(--ink-muted);
|
||||
}
|
||||
@media (max-width: 45em){
|
||||
.footer-grid{ grid-template-columns:1fr; gap:2rem; }
|
||||
}
|
||||
|
||||
/* scroll reveal */
|
||||
.reveal{ opacity:0; transform:translateY(0.875rem); transition:opacity .6s ease, transform .6s ease; }
|
||||
.reveal.is-visible{ opacity:1; transform:none; }
|
||||
@media (prefers-reduced-motion: reduce){
|
||||
.reveal{ opacity:1; transform:none; transition:none; }
|
||||
}
|
||||
Reference in new issue
Block a user