/* =============================================================================
   HPN design tokens

   Replaces what the GoDaddy site had: THREE CSS variables, a flat type scale
   (544 elements at 16px on /karaoke against 33 at 22px), 221 elements at
   border-radius 0 with two pill exceptions, three one-off shadows, and FIVE
   purples used interchangeably.

   Every value here is deliberate. Craig picks from these via block options; he
   never types a colour, which is why the site cannot drift off-brand.
   ============================================================================= */

:root {
  /* Declare the scheme. Without this, Chrome's "Auto Dark Mode for Web Contents"
     treats the page as un-themed and inverts it itself: the offering cards come out
     charcoal, the brand panel becomes a flat dark grey box, and the palette below stops
     describing what anyone actually sees. Naming a scheme is the documented opt-out.

     `light` because that is what this design is — a dark header and footer around a
     light body, with the contrast ratios in this file measured against light surfaces.
     A genuine dark theme is a palette-wide piece of work, not a browser filter. */
  color-scheme: light;

  /* --- Brand ---------------------------------------------------------------
     #8D0BAB is the real brand purple — it is the live site's theme-color and
     the favicon colour. The other four purples found in the audit (#C938EB,
     #E5A9FE, #DE8AFD, #B311D9) were link and hover states that had drifted;
     they are replaced by a deliberate ramp derived from the brand hue. */
  --brand-50:  #f7e9fb;
  --brand-100: #ecc9f5;
  --brand-200: #dda2ee;
  --brand-300: #c86fe3;
  --brand-400: #b23fd6;
  --brand-500: #8d0bab;   /* brand */
  --brand-600: #7a0994;
  --brand-700: #620776;
  --brand-800: #4a0559;
  --brand-900: #33033d;

  /* --- Neutrals ------------------------------------------------------------ */
  --ink-000: #ffffff;
  --ink-050: #f7f7f7;
  --ink-100: #e2e2e2;
  --ink-200: #c4c4c4;
  --ink-300: #a4a4a4;
  --ink-400: #808080;
  --ink-500: #5c5c5c;
  --ink-600: #3d3d3d;
  --ink-700: #2a2a2a;
  --ink-800: #1e1e1e;
  --ink-900: #161616;   /* the site's existing surface colour */

  /* --- Semantic ------------------------------------------------------------
     Contrast against the surface each is used on is verified in the comments.
     The old site passed text-on-colour but FAILED text-on-image on all four
     hero slides (worst 2.65:1 against a 3.0:1 requirement) — hence the scrim
     tokens below, which exist so that can never happen again. */
  --surface:            var(--ink-000);
  --surface-muted:      var(--ink-050);
  --surface-inverse:    var(--ink-900);
  /* Three more surfaces, named because they were being spelled out of the raw ramp.

     `background: var(--ink-000)` on a card is not "white", it is "the surface a card
     sits on, which happens to be white here". Forty-odd declarations across five
     stylesheets made that substitution by hand, and every one of them was a place a
     dark theme would have left a white box on a black page. Naming them is what makes
     the theme below a palette swap instead of a search-and-replace.

     RAISED is a card, an input, a chat bubble — something sitting ON the page.
     SUNKEN is a photo placeholder, a track, a tag — a well cut INTO it.
     STRONG is body text with emphasis, one step up from --text-muted. */
  --surface-raised:     var(--ink-000);
  --surface-sunken:     var(--ink-100);
  --text-strong:        var(--ink-700);   /* 13.96:1 on white — measured */
  --text:               var(--ink-900);   /* 18.10:1 on white — measured */
  --text-muted:         var(--ink-500);   /*  6.69:1 on white — measured */
  --text-on-inverse:    var(--ink-050);   /* 16.89:1 on #161616 — measured */
  --text-on-brand:      var(--ink-000);   /*  7.59:1 on #8D0BAB — measured */
  /* Brand-coloured TEXT, which is a different job from brand-coloured fill.

     A price, a "See foam parties", a venue time — none of them are links, but all of
     them were written as --brand-600 and all of them are text on the page surface. On a
     dark page that is #7a0994 on #131316: 2.03:1, unreadable. The fills stay put (white
     on brand purple is the same 7.59:1 in both themes); only the ink climbs the ramp.

     --link is defined FROM these rather than beside them, so a link and a price cannot
     drift into two different purples. */
  --brand-ink:          var(--brand-600);
  --brand-ink-strong:   var(--brand-700);
  --link:               var(--brand-ink);
  --link-hover:         var(--brand-ink-strong);

  /* Translucent cards. The section tint showing through is the point of them, so the
     dark theme lifts with white at low alpha rather than painting a solid panel — the
     gradient underneath still reads. */
  /* Brand-tinted panels: a selected choice, an unread row, a hover fill, the step you
     have finished. These were --brand-50 and --brand-100 written directly, which is a
     LIGHT purple — fine while the ink on them was a dark purple, and invisible the
     moment the ink flipped. The completed steps in the planner came out as lavender
     pills with lavender labels: three blank chips.

     Both themes put the wash and its ink at opposite ends of the ramp, so the pair
     measures the same 7.86:1 either way round. */
  /* An error panel. portal.css asked for --danger-bg, which was never defined anywhere,
     so it fell through to its own fallback and drew failed messages on the BRAND wash —
     a pale purple, which is the colour of a selected choice, not of something going
     wrong. Defined here and named for what it is. */
  --danger-wash:         #fdecea;
  --brand-wash:          var(--brand-50);
  --brand-wash-strong:   var(--brand-100);
  --surface-veil:        rgba(255,255,255,.92);
  --surface-veil-strong: rgba(255,255,255,.86);
  --border:             var(--ink-100);   /*  1.30:1 on white — DECORATION ONLY */

  /* The border of a form control, which is not decoration and does not get to be this
     faint. WCAG 2.2 SC 1.4.11 asks for 3:1 on the visual boundary that identifies a user
     interface component, and on a white field on a white page that border is the only
     thing saying "this is a field" — there is nothing else to identify it by. Every
     input, select and textarea on the site was drawing it in --border at 1.30:1.

     --border stays where it is. Dividers and card outlines ARE decoration, SC 1.4.11
     exempts them by name, and darkening the token would have restyled the whole site to
     fix a form problem. */
  --border-control:     #8a8a8a;          /*  3.45:1 on white, 3.22:1 on #f7f7f7 */
  --focus-ring:         var(--brand-400); /*  4.59:1 on white, 4.06:1 on #161616 */
  /* On purple the default ring is 1.65:1, and 1.12:1 at the lightest point of the
     CTA band. Named here rather than written inline in base.css so check_contrast
     can see it -- the checker reads this file, so a value it cannot read is a
     value nothing verifies. */
  --focus-ring-on-brand: var(--ink-000); /*  5.14:1 at the band's lightest point */

  /* Hero scrim. Text over photography needs this — it is not decorative. */
  --scrim-strong: linear-gradient(180deg, rgba(0,0,0,.35) 0%, rgba(0,0,0,.72) 100%);
  --scrim-soft:   linear-gradient(180deg, rgba(0,0,0,.15) 0%, rgba(0,0,0,.55) 100%);

  /* --- Type ----------------------------------------------------------------
     Two families, not four. The old site leaked Nunito and Times New Roman
     onto every page alongside Montserrat and Archivo Black. */
  /* Fallbacks matter: if the display webfont fails, `system-ui` is the SAME face as the
     body stack, so every heading silently loses its hierarchy. "Arial Black" ships with
     Windows and macOS, so a US visitor keeps a heavy display texture either way. */
  --font-display: "Archivo Black", "Arial Black", "Helvetica Neue", system-ui, sans-serif;
  --font-body:    Montserrat, system-ui, -apple-system, "Segoe UI", Roboto,
                  "Helvetica Neue", Arial, sans-serif,
                  "Apple Color Emoji", "Segoe UI Emoji";

  /* A real scale, fluid between 360px and 1280px viewports. */
  /* Trimmed about 6% at the top of the range, at Craig's request that everything read a
     little smaller. Body text was rendering at 18px on a desktop, which is generous; it
     is now ~17px.

     The two smallest steps keep their FLOORS. They are already caption size, and this is
     a site people book a wedding on — shrinking helper text below 0.72rem to make a page
     look tidier trades readability for tidiness, which is the wrong way round. Only their
     ceilings come down, so the ramp stays proportional.

     The larger steps carry most of the reduction, because headings are what make a page
     feel long: h2 goes from 45.8px to about 42px at 1280. */
  --step--2: clamp(0.72rem, 0.70rem + 0.09vw, 0.76rem);  /* captions, helper text */
  --step--1: clamp(0.83rem, 0.80rem + 0.12vw, 0.86rem);
  --step-0:  clamp(1.00rem, 0.96rem + 0.17vw, 1.06rem);
  --step-1:  clamp(1.14rem, 1.06rem + 0.36vw, 1.33rem);
  --step-2:  clamp(1.35rem, 1.22rem + 0.60vw, 1.68rem);
  --step-3:  clamp(1.62rem, 1.40rem + 1.00vw, 2.12rem);
  --step-4:  clamp(1.94rem, 1.61rem + 1.50vw, 2.67rem);
  --step-5:  clamp(2.33rem, 1.83rem + 2.25vw, 3.37rem);

  /* Leading varies with size. One "tight" value cannot serve a 58px display headline and
     a 29px subhead at once — which is why ad-hoc line-heights (1.02, 1.1, 1.15, 1.2, 1)
     had accumulated across four stylesheets. */
  --leading-display: 1.05;   /* --step-4 and up */
  --leading-tight:   1.15;
  --leading-snug:    1.3;    /* small headings, card titles */
  --leading-body:    1.6;
  --leading-relaxed: 1.75;   /* long-form prose */

  /* Tracking. Large heavy type needs to be pulled IN; small uppercase needs opening OUT.
     These five values were previously hardcoded in four files (.01em, .08em, .14em x3). */
  --tracking-display: -0.022em;  /* Archivo Black at 40px+ */
  --tracking-tight:   -0.01em;   /* mid-size headings */
  --tracking-normal:   0;
  --tracking-wide:     0.01em;   /* nav, dense UI text */
  --tracking-label:    0.08em;   /* uppercase section labels */
  --tracking-eyebrow:  0.14em;   /* uppercase micro-labels */

  /* Weights, named honestly. 600 was previously called "medium" (it is SemiBold), and
     "normal" and "regular" were two names for 400. Montserrat 500 was downloaded on every
     page load and never referenced by anything. */
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  /* --- Spacing (one scale, no free numbers) -------------------------------- */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs:  0.75rem;
  --space-s:   1rem;
  --space-m:   1.5rem;
  --space-l:   2rem;
  --space-xl:  3rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;

  /* --- Radius and elevation ------------------------------------------------ */
  /* Error state. 5.9:1 on white, so error text passes AA at body size. */
  /* Review stars. Two values because a gold that reads on white is muddy on the dark
     surfaces, and the brighter one fails AA on white.
     MEASURED, not estimated: the previous --star (#b7791f) was annotated "4.6:1" and is
     actually 3.64:1 — a real AA failure on a rating, which carries information rather
     than being decoration. Darkened until it passes. */
  --star:        #9a6410;   /* 4.99:1 on #ffffff */
  --star-on-dark: #f0c040;  /* 10.62:1 on #161616 */

  --danger:      #b3261e;

  /* Status fills. These were six literals sitting in components.css — a green tag, an
     amber tag and a cream warning note — and every one of them was a light pastel with
     dark text on it, which on a dark page is a lit panel in the middle of the room.
     Named here so the dark theme can restate them and check_contrast can measure both.
     The light values are byte-for-byte what shipped; nothing about the light site
     changes. */
  --tag-ok-surface:     #e4f5e9;
  --tag-ok-text:        #1c5730;   /* 7.35:1 on its surface — measured */
  --tag-warn-surface:   #fdeccd;
  --tag-warn-text:      #7a4a06;   /* 6.42:1 on its surface — measured */
  --note-warn-surface:  #fff8e6;
  --note-warn-border:   #f2dfae;

  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:  16px;
  --radius-pill: 999px;

  --shadow-1: 0 1px 2px rgba(0,0,0,.06), 0 1px 3px rgba(0,0,0,.10);
  --shadow-2: 0 2px 6px rgba(0,0,0,.08), 0 4px 12px rgba(0,0,0,.10);
  --shadow-3: 0 8px 24px rgba(0,0,0,.12), 0 2px 6px rgba(0,0,0,.08);

  /* --- Layout -------------------------------------------------------------- */
  --width-contained: 68rem;
  --width-wide:      82rem;
  --width-prose:     38rem;

  /* --- Motion --------------------------------------------------------------
     Deliberately short. The old site's only real animation was two INFINITE
     marquees, 97.97s and 74.24s, on elements 8906px and 6749px wide. */
  --ease: cubic-bezier(.2, .7, .3, 1);
  --dur-fast: 120ms;
  --dur:      200ms;
  --dur-slow: 320ms;

  /* Minimum interactive target. The audit found half to two-thirds of tappable
     elements under 44px on every page. */
  --tap-min: 44px;

  /* Header height, declared once. The full-bleed hero subtracts it so that the hero
     and the header fit one screen together; when these two drift apart the homepage
     headline drops below the fold. */
  --header-h: 5rem;   /* 80px */
}

/* =============================================================================
   Dark theme

   One block, keyed on an attribute, because the head script in base.html always
   resolves the visitor's choice to a concrete "light" or "dark" before the first
   paint. The obvious alternative — a prefers-color-scheme media query AND an
   attribute rule — means writing this palette twice and maintaining both, which is
   the kind of duplication that ends with a token fixed in one theme and not the
   other. Without JavaScript there is no attribute and the site stays light, which
   is exactly the site as it shipped, not a broken one.

   What this is NOT is an inversion of the ramp above. The ramp is used two ways:
   "white text on a dark band" (the header, the footer, the hero, the CTA sections)
   and "a light surface on a light page". Flipping the ramp would fix the second and
   destroy the first — the footer would turn white. So the dark bands keep their
   colours in both themes and only the SEMANTIC layer moves.

   Elevation still reads, which on a dark palette has to be built deliberately
   because shadows barely show: chrome sinks below the page, cards rise above it.
       inverse #0e0e11  <  surface #131316  <  raised #202028  <  sunken is a well
   Sunken is lighter than raised rather than darker for the same reason a hole in a
   dark room is not blacker than the room — there is nothing below black to go to.
   ============================================================================= */
:root[data-theme="dark"] {
  /* Native widgets follow: scrollbars, date pickers, the select drop-down, the
     spinner on a number input. Without it a dark page grows a white scrollbar. */
  color-scheme: dark;

  --surface:            #131316;
  --surface-muted:      #1b1b21;
  --surface-raised:     #202028;
  --surface-sunken:     #26262f;
  --surface-inverse:    #0e0e11;

  /* Not #ffffff. Pure white on near-black haloes — the glyph edges bloom and long
     paragraphs get harder to read, not easier. #ededf2 still measures 15.4:1. */
  --text:               #ededf2;
  --text-strong:        #ffffff;
  --text-muted:         #a6a6b2;
  --text-on-inverse:    #ededf2;
  /* Unchanged: the brand purple is the same purple in both themes, and white on it
     is the same 7.59:1 it always was. */
  --text-on-brand:      var(--ink-000);

  /* The link ramp turns over. --brand-600 is a 7:1 link on white and a 1.6:1 smudge
     on #131316 — the same token cannot serve both ends of the scale, so dark mode
     climbs the ramp instead of descending it. */
  --brand-ink:          var(--brand-200);
  --brand-ink-strong:   var(--brand-100);

  --danger-wash:         #3a1714;
  --brand-wash:          var(--brand-900);
  --brand-wash-strong:   var(--brand-800);
  --surface-veil:        rgba(255,255,255,.055);
  --surface-veil-strong: rgba(255,255,255,.09);

  --border:             #2f2f3a;
  /* Still SC 1.4.11: 3:1 against the field it outlines, measured on --surface-raised
     rather than on white. */
  --border-control:     #7b7b8a;
  --focus-ring:         var(--brand-300);

  /* #b3261e is a dark red for white paper and disappears into a dark page. Error
     text has to be readable at the moment somebody is stuck. */
  --danger:             #ff9a90;
  /* The gold that was mixed for dark surfaces already exists — the rating just
     stops asking for the one mixed for white. */
  --star:               var(--star-on-dark);

  /* Shadows do almost nothing on a dark ground: there is no light for them to take
     away. Deepened so the little that shows still separates a card from the page,
     and the real separation work is done by --surface-raised being lighter. */
  --shadow-1: 0 1px 2px rgba(0,0,0,.40), 0 1px 3px rgba(0,0,0,.34);
  --shadow-2: 0 2px 6px rgba(0,0,0,.44), 0 4px 12px rgba(0,0,0,.36);
  --shadow-3: 0 8px 24px rgba(0,0,0,.52), 0 2px 6px rgba(0,0,0,.40);

  /* Same three states, mixed the other way up: a dark fill with a light glyph. Keeping
     the hue and inverting the lightness is what makes a green tag still read as
     "good" rather than as a different component. */
  --tag-ok-surface:     #12301f;
  --tag-ok-text:        #7fdfa2;
  --tag-warn-surface:   #33290f;
  --tag-warn-text:      #f2c569;
  --note-warn-surface:  #2e2716;
  --note-warn-border:   #4a3f22;
}

/* Honour the OS setting. The old site had ZERO prefers-reduced-motion blocks
   while running two infinite animations. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 1ms;
    --dur: 1ms;
    --dur-slow: 1ms;
  }
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
