/* Fonts are vendored, not fetched. A Google Fonts <link> sends every guest's
   IP address to a third party on every page load, and cost the CSP four
   sources. Files come from @fontsource via `npm run fonts:vendor`.
   font-display: swap so text is readable before the face arrives. */

@font-face {
  font-family: 'Cinzel'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('/fonts/cinzel-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Cinzel'; font-style: normal; font-weight: 600;
  font-display: swap; src: url('/fonts/cinzel-latin-600-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Cinzel'; font-style: normal; font-weight: 700;
  font-display: swap; src: url('/fonts/cinzel-latin-700-normal.woff2') format('woff2');
}

@font-face {
  font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 300;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-300-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 500;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 600;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-600-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 300;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-300-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 400;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-400-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 500;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-500-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 600;
  font-display: swap; src: url('/fonts/cormorant-garamond-latin-600-italic.woff2') format('woff2');
}

@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 300;
  font-display: swap; src: url('/fonts/dm-sans-latin-300-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('/fonts/dm-sans-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 500;
  font-display: swap; src: url('/fonts/dm-sans-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Sans'; font-style: italic; font-weight: 300;
  font-display: swap; src: url('/fonts/dm-sans-latin-300-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Sans'; font-style: italic; font-weight: 400;
  font-display: swap; src: url('/fonts/dm-sans-latin-400-italic.woff2') format('woff2');
}

/* Public Sans backs --sans below, used by the passport.html staff portal only
   (tall x-height, unambiguous digits for PINs — see that page's own comment). */
@font-face {
  font-family: 'Public Sans'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('/fonts/public-sans-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Public Sans'; font-style: normal; font-weight: 500;
  font-display: swap; src: url('/fonts/public-sans-latin-500-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Public Sans'; font-style: normal; font-weight: 600;
  font-display: swap; src: url('/fonts/public-sans-latin-600-normal.woff2') format('woff2');
}

/* ═══════════════════════════════════════════════════════════════════════
   Estate Italiana — brand tokens and shared primitives
   ═══════════════════════════════════════════════════════════════════════
   One definition of the palette, type scale and motion rules for every page.
   The values were duplicated in nine inline <style> blocks and had already
   drifted: the marketing pages were still on a lighter gold (#C9A84C) and a
   muted blue (#7A99B2) that fails AA below 18px, while the passport pages had
   moved to the real brand values. Pages now define layout only; colour and
   type come from here.

   Estate Italiana is a members' society, not a punch card. The palette runs
   deep navy and warm gold, with paper and sand for ground. Restraint is the
   point: the member pass is the one loud object, everything else stays quiet.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Ground ────────────────────────────────────────────────────────── */
  /* Paper. Warmed from #F7FAFD (a cool, faintly blue white) to the redesign's
     #FBF7EE. Same lightness, so every text contrast ratio is unchanged, but the
     page stops reading like a clinic and starts reading like a room with lamps
     in it. The warm/cool alternation with --sabbia is what the redesign uses to
     separate sections without drawing rules everywhere. */
  --panna:       #FBF7EE;  /* paper */
  --bg:          #FBF7EE;
  --bg-alt:      #FFFFFF;
  --bg-blue:     #E8EFF6;
  --bg-deep:     #CFDDEA;
  --sabbia:      #F4ECDD;  /* warm card */
  --cream:       #F4ECDD;
  --page:        #FBF7EE;
  --page-2:      #F4ECDD;

  /* ── Notte, the house navy ─────────────────────────────────────────── */
  --notte:       #112B45;
  --navy:        #0E2338;  /* a shade under notte, for grounds and rules */
  --navy-2:      #112B45;
  --med-blue:    #1B3A57;
  --sky:         #35608D;  /* deep accent blue, AA on paper */
  --ink:         #112B45;
  --body:        #2A4258;
  --body-ink:    #2A4258;

  /* ── Oro ───────────────────────────────────────────────────────────── */
  --oro:         #E7D29A;  /* gold on navy only */
  --light-gold:  #E7D29A;
  --oro-antico:  #9A7B3C;  /* gold that holds up as text on paper */
  --gold:        #9A7B3C;
  --accent:      #9A7B3C;
  --accent-ink:  #6E5628;
  --accent-soft: rgba(231, 210, 154, 0.18);

  /* ── Muted text. #8595A3 and #7A99B2 are retired below 18px. ───────── */
  --ardesia:     #5A6B7A;
  --dim:         #5A6B7A;

  /* ── Lines ─────────────────────────────────────────────────────────── */
  --border:      rgba(14, 35, 56, 0.12);
  --border-md:   rgba(14, 35, 56, 0.20);
  --line:        rgba(14, 35, 56, 0.12);
  --card-line:   rgba(14, 35, 56, 0.12);
  --hairline-oro: rgba(231, 210, 154, 0.22);

  /* ── Status ────────────────────────────────────────────────────────── */
  --green:       #2E8B57;
  --green-bg:    #EBF5EF;
  --good:        #2E8B57;

  /* ── The pass ──────────────────────────────────────────────────────── */
  --pass-from:   #173354;
  --pass-to:     #0B1E33;

  /* ── Diary leather (Il Mio Diario only) ────────────────────────────── */
  --cover:       #6E5638;
  --cover-2:     #4A3B27;
  --cover-ink:   #F4ECDD;
  --cover-ink-dim: rgba(244, 236, 221, 0.72);
  --seal:        #9A2B2B;
  --seal-edge:   #6E1F1F;
  --seal-hi:     #C4483F;
  --seal-ink:    #F4ECDD;
  --card:        #FFFFFF;
  --app-bg:      #F7FAFD;
  --tab-bg:      rgba(255, 255, 255, 0.94);

  /* ── Type ──────────────────────────────────────────────────────────── */
  --display: 'Cinzel', Georgia, 'Times New Roman', serif;
  --serif:   'Cormorant Garamond', Georgia, serif;
  --sans:    'Public Sans', 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* Body never below 16px; Cinzel micro-labels never below 11px. */
  --t-eyebrow: 0.6875rem;  /* 11px */
  --t-body:    1rem;       /* 16px */

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ═══ Section eyebrow ═══════════════════════════════════════════════════
   The small Cinzel label above a heading. Italian section name, English
   body underneath, which is the house bilingual split. */
.ei-eyebrow {
  font-family: var(--display);
  font-size: var(--t-eyebrow);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--oro-antico);
  margin: 0 0 0.7rem;
}
.ei-eyebrow--on-navy { color: var(--oro); opacity: 0.75; }

/* ═══ Tier honorific chip ═══════════════════════════════════════════════
   A gold dot and the honorific. Used on the pass and in the staff panel. */
.ei-tier {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.32rem 0.9rem 0.34rem;
  border: 1px solid rgba(231, 210, 154, 0.55);
  border-radius: 999px;
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--oro);
  white-space: nowrap;
}
.ei-tier::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--oro);
  flex: none;
}
/* On paper the gold has to darken to stay legible. */
.ei-tier--paper {
  color: var(--oro-antico);
  border-color: rgba(154, 123, 60, 0.45);
  background: rgba(231, 210, 154, 0.12);
}
.ei-tier--paper::before { background: var(--oro-antico); }

/* ═══ The member pass ═══════════════════════════════════════════════════
   The one object on the site allowed to be loud. Navy gradient under a gold
   hairline cap, the house name and monogram, then the member's standing, then
   the rotating QR on a paper panel. Nothing else competes with it. */
.ei-pass {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  background: linear-gradient(158deg, var(--pass-from) 0%, var(--pass-to) 100%);
  box-shadow: 0 18px 44px -22px rgba(11, 30, 51, 0.75), 0 2px 8px rgba(11, 30, 51, 0.18);
  isolation: isolate;
}
/* The gold cap. A physical edge, like the gilt on a membership card. */
.ei-pass::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, #B99B57 0%, var(--oro) 38%, #F2E4BE 52%, var(--oro) 66%, #B99B57 100%);
  z-index: 2;
}

.ei-pass__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.6rem 1.5rem 1.25rem;
  border-bottom: 1px solid var(--hairline-oro);
}
.ei-pass__house {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #FFFFFF;
  margin: 0;
  line-height: 1.2;
}
.ei-pass__season-name {
  font-family: var(--serif);
  font-size: 1.0625rem;
  font-style: italic;
  color: rgba(231, 210, 154, 0.9);
  margin: 0.2rem 0 0;
}
.ei-pass__monogram {
  flex: none;
  width: 46px; height: 46px;
  border: 1px solid rgba(231, 210, 154, 0.5);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--oro);
}

.ei-pass__grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.15rem 1rem;
  padding: 1.35rem 1.5rem 1.5rem;
}
.ei-pass__label {
  font-family: var(--display);
  font-size: var(--t-eyebrow);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(231, 210, 154, 0.68);
  margin: 0 0 0.3rem;
}
.ei-pass__value {
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: 600;
  color: #FFFFFF;
  margin: 0;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
.ei-pass__value--oro { color: var(--oro); }
.ei-pass__value--plain {
  font-family: var(--serif);
  font-size: 1.15rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}
.ei-pass__cell--right { text-align: right; }

/* The QR sits on paper, not on navy: scanners want the quiet zone light. */
.ei-pass__qr {
  background: #FFFFFF;
  padding: 1.6rem 1.5rem 1.4rem;
  text-align: center;
}
.ei-pass__qr-frame {
  width: min(220px, 62%);
  margin: 0 auto 0.9rem;
}
.ei-pass__qr-frame svg { display: block; width: 100%; height: auto; }
.ei-pass__note {
  font-family: var(--sans);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: var(--ardesia);
  margin: 0;
}
.ei-pass__code {
  font-family: 'Courier New', monospace;
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--notte);
  margin: 0 0 0.35rem;
}

/* A single sheen crosses the pass once when it appears. Motion is a guest. */
@keyframes ei-sheen {
  from { transform: translateX(-120%) skewX(-18deg); }
  to   { transform: translateX(320%)  skewX(-18deg); }
}
.ei-pass__sheen {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 42%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.13), transparent);
  animation: ei-sheen 1.5s var(--ease) 0.35s both;
}

@keyframes ei-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.ei-rise { animation: ei-rise 0.5s var(--ease) both; }

/* ═══ Member passport surfaces ══════════════════════════════════════════ */
.ei-greeting {
  font-family: var(--display);
  font-size: clamp(1.5rem, 4.5vw, 2rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--notte);
  margin: 0 0 1.15rem;
}
.ei-greeting em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 500;
  color: var(--oro-antico);
}

.ei-idline {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin: 1.5rem 0;
}
.ei-idline > div:first-child { flex: 1 1 12rem; }
.ei-idline__name {
  font-family: var(--display);
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--notte);
}
.ei-idline__meta {
  font-family: var(--serif);
  font-size: var(--t-body);
  color: var(--ardesia);
  margin-top: 0.2rem;
  overflow-wrap: anywhere;
}

.ei-badge-note {
  background: rgba(231, 210, 154, 0.16);
  border-left: 3px solid var(--oro);
  padding: 0.95rem 1.2rem;
  margin: 0 0 1.6rem;
  font-family: var(--serif);
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--accent-ink);
}
.ei-badge-note strong { color: var(--notte); }

.ei-season__count {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--ardesia);
  margin: 0 0 1.1rem;
}

/* The season's evenings, as a timeline down a gold rule. */
.ei-visits { list-style: none; margin: 0; padding: 0 0 0 1.4rem; position: relative; }
.ei-visits::before {
  content: '';
  position: absolute;
  left: 3px; top: 6px; bottom: 6px;
  width: 1px;
  background: rgba(154, 123, 60, 0.45);
}
.ei-visit { position: relative; padding: 0 0 1.25rem; }
.ei-visit::before {
  content: '';
  position: absolute;
  left: -1.4rem; top: 7px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--oro-antico);
}
.ei-visit:last-child { padding-bottom: 0; }
.ei-visit__title {
  font-family: var(--display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--notte);
  line-height: 1.3;
}
.ei-visit__meta {
  font-family: var(--serif);
  font-size: var(--t-body);
  color: var(--ardesia);
  margin-top: 0.2rem;
}
.ei-visit--empty::before { background: rgba(154, 123, 60, 0.35); }
.ei-visit--empty .ei-visit__title { font-family: var(--serif); font-style: italic; font-weight: 500; }

/* ═══ The data note ═════════════════════════════════════════════════════
   Data rights, in a bar. This started as a full card with two solid buttons,
   one of them red, which made closing your account look like the main event on
   the page. It is a quiet footnote instead: small type, hairline rule, plain
   links. Still easy to find, no longer shouting. */
.ei-data-note,
.data-note {
  margin-top: 2.25rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--border);
}
.data-note p {
  font-family: var(--serif);
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ardesia);
  margin: 0;
}
.data-note a {
  color: var(--sky);
  text-decoration: underline;
  text-underline-offset: 2px;
  white-space: nowrap;
  /* Comfortably tappable without becoming a button again. Plain links still
     have to clear 24px (WCAG 2.5.8); at 0.2rem of padding this one came out
     at 21. */
  display: inline-block;
  padding: 0.45rem 0;
  min-height: 26px;
}
.data-note a:hover { color: var(--notte); }
.data-note__leave { color: var(--ardesia); }
.data-note__fine {
  font-size: 0.82rem;
  margin-top: 0.35rem;
  opacity: 0.85;
}

/* The `hidden` attribute only hides via a UA rule of `display: none`, which any
   author `display` declaration outranks. So `el.hidden = true` silently does
   nothing to, say, `.news-card-read { display: flex }` — the element stays on
   screen while the code that hid it reads as correct. This restores the meaning
   of the attribute site-wide. */
[hidden] { display: none !important; }

/* ═══ Small-screen type floor ════════════════════════════════════════════
   The brand runs on letterspaced Cinzel micro-caps — section eyebrows, menu
   labels, tab buttons. They are a deliberate device and they read larger than
   their pixel size suggests, because the tracking opens them up. On a desktop
   at arm's length that holds.

   On a phone it stops holding somewhere under 11px, and several of these sit at
   10.4–11.5px. Rather than redesigning the device, raise the floor where it
   actually matters: small screens. Tracking is eased slightly at the same time,
   since wide tracking on small type is what makes it swim.

   Nothing here changes the desktop rendering. */
@media (max-width: 640px) {
  /* Prefixed with `body` for (0,1,1). A bare class here is (0,1,0) and loses
     to the identical selector in each page's own <style>, which loads after
     this file — media queries carry no specificity of their own. Third time
     this exact trap has come up in this codebase; see also nav .nav-book. */
  body .section-tag,
  body .menu-section-label,
  body .footer-heading,
  /* Pages scope it as .footer-col .footer-heading — (0,2,0) — so match it. */
  body .footer-col .footer-heading,
  body .visit-label,
  body .page-hero-tag,
  body .cal-list-status,
  body .cal-dayname {
    font-size: 0.72rem;      /* 11.5px */
    letter-spacing: 0.16em;
  }
  /* Interactive labels get a touch more, being tap targets people aim at. */
  body .tab-btn,
  body .filter-btn,
  body .nav-book,
  body .mobile-nav-book {
    font-size: 0.78rem;      /* 12.5px */
    letter-spacing: 0.12em;
  }
}

/* ═══ Touch targets ═════════════════════════════════════════════════════
   Sizes measured in-browser at 390px. Selectors here are deliberately one step
   more specific than the page rules they correct, because this file loads
   before the pages' own <style> and would otherwise lose the cascade.

   The wordmark links (.nav-logo, .footer-logo, .p-logo) are left alone: they
   run 170 to 310px wide, so there is plenty to hit, and forcing height on them
   would drag their baseline-aligned sub-label out of position. */

/* The hamburger is the only way to navigate on a phone. It was 36x36. */
nav .nav-toggle { min-width: 44px; min-height: 44px; }

/* Nav call to action and the passport back link, 31px and 30px tall. */
nav .nav-book,
nav .nav-back {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* Dropdown items under "Explore" were ~31px. */
nav .nav-drop-menu li a {
  display: flex;
  align-items: center;
  min-height: 44px;
}

/* Below the hamburger breakpoint the bar holds the wordmark, the booking pill
   and the toggle at once. Measured at 320px the row wants 429px, so the pill
   and the toggle are pushed off the right edge and cannot be tapped at all.
   Every page's mobile overlay carries its own booking link, so the pill in the
   bar is redundant there — hide it and the row fits.

   This lives here, at `nav .nav-book`, rather than in each page's own <style>:
   the rule above is one step more specific than a bare `.nav-book`, so a
   page-level `.nav-book { display: none }` inside a media query loses the
   cascade. Media queries carry no specificity of their own. */
/* ── The nav breakpoint ───────────────────────────────────────────────────
   Every page collapsed its nav to a hamburger at 768px, but the desktop nav
   does not actually FIT until about 980px. Measured across the site, the bar
   overflowed its own bounds by 43–182px everywhere between 800 and 900px, and
   the wordmark's subtitle ran straight through the links. Nothing caught it,
   because `nav` is position:fixed and fixed elements do not extend the
   document's scrollWidth — the page never scrolled sideways, it just looked
   broken.

   One rule, here, rather than in nine page stylesheets: the pages' own 768px
   blocks carry their own layout (hero padding, grid collapses) and should not
   be dragged to a different number just to fix the nav.

   Selectors are `nav .x` — one step more specific than the page rules they
   override, because this file loads first and would otherwise lose the
   cascade. */
@media (max-width: 980px) {
  nav { padding: 1rem 1.2rem; }
  nav .nav-links { display: none; }
  nav .nav-book { display: none; }
  nav .nav-toggle { display: flex; }
  /* "Italian Aperitivo Bar · Downtown Leesburg" is the first thing to go: it is
     a flourish, and it is what collides with the links first. */
  nav .nav-logo-sub { display: none; }
}

/* Hero buttons sat at 41px, just under the line. */
a.btn-solid,
a.btn-outline,
a.mobile-nav-book {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
}

/* Section tab buttons on the home page measured 41px. */
button.tab-btn,
button.hero-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
}

/* Text fields: 44px so a thumb lands cleanly. Checkboxes keep their own size,
   they have a full-width <label> to tap. */
.form-group input:not([type="checkbox"]):not([type="radio"]),
.form-group select,
.form-group textarea { min-height: 44px; }

/* The consent box is a required legal interaction, so make it easy to hit. */
input#reg-consent { width: 20px; height: 20px; }

/* ═══ Quality floor ═════════════════════════════════════════════════════ */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--oro-antico);
  outline-offset: 2px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .ei-pass__sheen { display: none; }
  .ei-rise { animation: none; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

@media (max-width: 480px) {
  .ei-pass__head { padding: 1.35rem 1.15rem 1.1rem; }
  .ei-pass__grid { padding: 1.15rem 1.15rem 1.3rem; }
  .ei-pass__value { font-size: 1.15rem; }
  .ei-pass__qr { padding: 1.35rem 1.15rem 1.2rem; }
  .ei-pass__qr-frame { width: min(200px, 72%); }
}
