/* ==========================================================================
   Kingdom Auto — Wednesday Happy Hour, "The Oil Drop Journey"
   (/happy-hour/oil-drop)   —   concept B

   Self-contained. Loaded ONLY by views/public/happy-hour-drop.ejs, which
   renders with layout:false. Nothing here touches the rest of the site, and
   nothing here touches /happy-hour (concept A, hh- prefix).
   Class prefix is od- (never ad-*, which ad blockers hide).

   THE ENHANCEMENT CONTRACT — the other half of /js/happy-hour-drop.js:

     (no class)    RESOLVED. Line drawn, every scene finished, all copy and
                   both CTAs in place. What a reader gets with JS off, JS
                   still loading, or reduced motion on. Read the file this way
                   first: every rule below is the finished page, and the
                   .od-motion block is the only thing that winds it back.
     .od-motion    on <html>, set in <head> before first paint. Winds each
                   scene back to its start and hands control to --sp / --jp.
     .od-play      the opening fall is running.

   PALETTE — the same warm cream-and-navy the rest of kingdomautoanddetail.ca
   runs on, so a reader arriving from an ad and a reader arriving from the home
   page are looking at the same business. Every ground, ink and chrome value
   below is lifted straight out of design-system.css; nothing here invents a
   colour the site does not already use.

   Three colours, three JOBS, and nothing borrows another's job:

     navy    #0F2547  KINGDOM. --kingdom-navy. Headlines, the machine, every
                      technical line: engine, tubes, filter, bezels. On cream
                      the machine is DRAWN IN NAVY — the old dark treatment
                      drew it in champagne, which simply vanishes on a light
                      ground.
     blue    #2E6BD6  INTERFACE. --kingdom-blue. The CTA, links, chrome.
                      Accent text uses --kingdom-blue-hover (#1F53B3), which
                      clears 6.8:1 on the cream ground where #2E6BD6 does not.
     amber   #C07C1E  THE OIL, and only ever the oil — the drop, the line, the
                      liquid in the tubes, the lit arc, the ring that closes
                      around the button. If it is amber, it is oil.

   One thing inverts when the ground does: on black, "lit" oil meant BRIGHTER;
   on cream it means DARKER. --od-oil-lit is still the emphasis amber, it is
   just now the one with more contrast rather than more glow, because a pale
   gold on cream is unreadable.

   There is deliberately no red: Kingdom's brand is navy/cream, and a red CTA
   would be a colour the business does not actually own.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */
.od {
  /* Ground — the site's own cream surfaces, straight from design-system.css:
     --bg-body, --bg-panel, --bg-card, --border-color, --border-subtle. */
  --od-void:   #FBFAF7;   /* the page */
  --od-pit:    #F5F2EC;   /* recessed panels */
  --od-card:   #FFFFFF;   /* raised cards */
  --od-steel:  #EAE5DB;   /* hairline */
  --od-steel-2:#D7D0C2;   /* stronger hairline */

  /* Ink — all checked against --od-void */
  --od-ink:    #0F2547;   /* 14.6:1 on the cream ground */
  --od-ink-2:  #2F3A4F;   /* 10.9:1 */
  --od-mute:   #5F6B80;   /*  5.2:1 */
  --od-faint:  #6E7A90;   /*  4.6:1 — still AA for the finest print */

  /* Kingdom */
  --od-machine:   #1C3E73;   /* --kingdom-navy-700: every technical outline */
  --od-blue:      #2E6BD6;   /* --kingdom-blue */
  --od-blue-deep: #1F53B3;   /* CTA fill: white label clears 7.1:1 */
  --od-blue-lit:  #1F53B3;   /* accents/links on the cream ground: 6.8:1 */

  /* Oil */
  --od-oil-deep: #6E3D0C;
  --od-oil:      #C07C1E;    /* the line: 3.3:1, clears AA for graphics */
  --od-oil-lit:  #9A5B12;    /* oil AS TEXT: 5.2:1 */
  --od-oil-spec: #E9B565;

  /* Lines */
  --od-line:      rgba(15, 37, 71, 0.14);
  --od-line-soft: rgba(15, 37, 71, 0.07);

  /* Shadows — navy-tinted and soft, the same family as --shadow-* on the site.
     A light page needs depth from shadow where a dark one got it from glow. */
  --od-shadow-sm: 0 1px 2px rgba(15,37,71,0.06), 0 1px 1px rgba(15,37,71,0.04);
  --od-shadow-md: 0 4px 10px rgba(15,37,71,0.07), 0 2px 4px rgba(15,37,71,0.04);
  --od-shadow-lg: 0 10px 24px rgba(15,37,71,0.10), 0 4px 8px rgba(15,37,71,0.05);

  /* Motion — weighted and viscous. No springs, no bounce: oil does not bounce. */
  --od-ease:     cubic-bezier(0.22, 0.61, 0.36, 1);
  --od-ease-out: cubic-bezier(0.16, 1, 0.30, 1);
  --od-ease-oil: cubic-bezier(0.55, 0.02, 0.24, 1);   /* the fall */
  --od-t-fast: 180ms;
  --od-t:      380ms;
  --od-t-slow: 820ms;

  /* Rhythm */
  --od-gutter:  clamp(1.15rem, 5vw, 4rem);
  --od-max:     1200px;
  --od-section: clamp(4.25rem, 9vw, 8.5rem);

  /* The rail: where the oil line sits on narrow screens. */
  --od-rail: 26px;

  /* The hero engine, and from it the exact height of the oil filler cap.
     The engine SVG is 760x300 with its cap at y=56, so the cap sits
     (300-56)/300 = 0.8133 of the artwork's height above its own base. */
  --od-eng-w: min(760px, 94vw);
  --od-eng-h: calc(var(--od-eng-w) * 0.3947);
  --od-eng-bottom: 3.5rem;
  --od-port: calc(var(--od-eng-bottom) + 0.8133 * var(--od-eng-h));
  --od-fall-dist: 54svh;

  /* Scroll progress. Overwritten per element by happy-hour-drop.js. */
  --jp: 1;
  --sp: 1;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Keep the sticky booking bar off any control the keyboard focuses.
     WCAG 2.2 — focus-not-obscured. */
  scroll-padding-bottom: 6.5rem;
  scroll-padding-top: 5rem;
}

body.od {
  margin: 0;
  background: var(--od-void);
  color: var(--od-ink-2);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; max-width: 100%; }
svg { height: auto; }
.od p, .od h1, .od h2, .od ul { margin: 0; }
.od ul { list-style: none; padding: 0; }

::selection { background: #E8F0FB; color: var(--od-ink); }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--od-blue-lit);
  outline-offset: 3px;
  border-radius: 2px;
}

.od-wrap {
  width: 100%;
  max-width: var(--od-max);
  margin-inline: auto;
  padding-inline: var(--od-gutter);
}

.od-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.od-skip {
  position: absolute; top: 0; left: 0; z-index: 200;
  transform: translateY(-120%);
  background: var(--od-blue-deep); color: #FFFFFF;
  padding: 0.75rem 1.25rem; font-weight: 600; text-decoration: none;
}
.od-skip:focus { transform: translateY(0); }

/* --------------------------------------------------------------------------
   Type
   -------------------------------------------------------------------------- */
.od-eyebrow {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--od-machine);
  display: flex; align-items: center; gap: 0.7em;
}
.od-eyebrow__n {
  color: var(--od-blue-lit);
  padding-right: 0.7em;
  border-right: 1px solid var(--od-line);
}

.od-h2 {
  font-family: 'Archivo', 'Inter', sans-serif;
  font-size: clamp(2.05rem, 5.6vw, 3.7rem);
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.028em;
  color: var(--od-ink);
  margin-top: 1.1rem;
  text-wrap: balance;
}

.od-lede {
  font-size: clamp(1.05rem, 2.1vw, 1.3rem);
  line-height: 1.5;
  text-wrap: pretty;
  color: var(--od-ink-2);
  max-width: 34ch;
}
.od-body {
  margin-top: 1.1rem;
  max-width: 42ch;
  color: var(--od-ink-2);
}
.od-fine {
  margin-top: 1.6rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--od-mute);
  max-width: 44ch;
}

/* The price. Tabular figures so it can never reflow mid-animation. */
.od-price {
  font-family: 'Archivo', 'Inter', sans-serif;
  font-weight: 800;
  line-height: 0.82;
  letter-spacing: -0.045em;
  color: var(--od-ink);
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: flex-start;
  white-space: nowrap;
}
.od-price__sym {
  font-size: 0.34em;
  font-weight: 700;
  margin-top: 0.2em;
  margin-right: -0.03em;
  color: var(--od-oil-lit);
  letter-spacing: 0;
}
.od-price__cents {
  font-size: 0.34em;
  font-weight: 700;
  margin-top: 0.16em;
  margin-left: 0.01em;
  color: var(--od-oil-lit);
  letter-spacing: 0;
}
.od-price--hero { font-size: clamp(4.6rem, 17vw, 9.5rem); }
.od-price--mid  { font-size: clamp(3.6rem, 11vw, 6rem); justify-content: center; }
.od-price--cta  { font-size: clamp(4rem, 13vw, 7rem); justify-content: center; }

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.od-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.6rem;
  min-height: 52px;                    /* comfortably over the 44px floor */
  padding: 0.95rem 1.9rem;
  border-radius: 9999px;               /* --radius-full, like every other
                                          control on kingdomautoanddetail.ca */
  font-family: 'Inter', sans-serif;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--od-t-fast) var(--od-ease),
              border-color var(--od-t-fast) var(--od-ease),
              color var(--od-t-fast) var(--od-ease),
              transform var(--od-t-fast) var(--od-ease);
}
.od-btn--primary {
  background: var(--od-blue-deep);
  color: #FFFFFF;
  border: 1px solid var(--od-blue-deep);
  /* A light page gets its depth from shadow, where the dark one got it from
     glow. Without this the primary CTA sits flat on the cream. */
  box-shadow: 0 6px 16px -6px rgba(31, 83, 179, 0.45);
}
.od-btn--primary:hover { background: var(--od-blue); border-color: var(--od-blue); }
.od-btn--primary:active { transform: translateY(1px); }
.od-btn--ghost {
  background: var(--od-card);
  color: var(--od-ink);
  border: 1px solid var(--od-steel-2);
  box-shadow: var(--od-shadow-sm);
}
.od-btn--ghost:hover { border-color: var(--od-blue); background: #E8F0FB; color: var(--od-blue-deep); }
.od-btn--xl { min-height: 60px; padding: 1.15rem 2rem; font-size: 1.0625rem; }
.od-btn--block { display: flex; width: 100%; }

.od-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--od-mute);
  flex: none;
}
.od-dot--live { background: var(--od-oil); box-shadow: 0 0 0 4px rgba(192,124,30,0.20); }

/* --------------------------------------------------------------------------
   Top bar
   -------------------------------------------------------------------------- */
.od-top {
  position: absolute; top: 0; left: 0; right: 0; z-index: 40;
  padding-top: max(1rem, env(safe-area-inset-top));
}
.od-top__row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.od-top__mark { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; }
.od-top__mark img { width: 34px; height: auto; }
.od-top__name {
  font-family: 'Archivo', sans-serif;
  font-size: 0.8125rem; font-weight: 700; letter-spacing: 0.02em;
  color: var(--od-ink); line-height: 1.15;
  display: flex; flex-direction: column;
}
.od-top__name span {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.625rem; font-weight: 400; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--od-blue-lit);
}
.od-top__tel {
  display: inline-flex; align-items: center; gap: 0.5rem;
  min-height: 44px; padding: 0 0.35rem;
  font-size: 0.875rem; font-weight: 500; color: var(--od-ink-2);
  text-decoration: none; white-space: nowrap;
}
.od-top__tel:hover { color: var(--od-blue-lit); }
.od-top__tel svg { color: var(--od-blue-lit); }

/* --------------------------------------------------------------------------
   SCENE 1 — the fall, and the offer
   -------------------------------------------------------------------------- */
.od-hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: clamp(5.5rem, 13vh, 8rem);
  /* Stop the copy exactly above the filler cap, so the drop lands in the
     engine and not on the price. */
  padding-bottom: calc(var(--od-port) + 2.5rem);
  overflow: hidden;
  isolation: isolate;
  text-align: center;
}

/* A warm wash rising off the engine, so the cream deepens toward the machine
   instead of ending at a hard edge. Deliberately weak: the price sits on it. */
.od-hero::after {
  content: '';
  position: absolute; inset: auto 0 0 0; height: 62%;
  /* The ellipse is centred INSIDE the box and reaches zero before the bottom
     edge. Centring it below the edge (which the dark treatment could get away
     with) leaves a warm band cut off by a straight line — invisible on black,
     an obvious seam on cream. */
  background: radial-gradient(ellipse 70% 52% at 50% 48%,
              rgba(192,124,30,0.16) 0%, rgba(192,124,30,0.05) 45%, transparent 72%);
  pointer-events: none; z-index: -2;
}

.od-hero__stage { position: absolute; inset: 0; z-index: -1; pointer-events: none; }

.od-hero__engine {
  position: absolute;
  left: 50%;
  bottom: var(--od-eng-bottom);
  width: var(--od-eng-w);
  transform: translateX(-50%);
}
/* The galleries are plumbing, not decoration: barely there until oil is in them.
   Amber needs more presence on cream than it did on black to read at all. */
.od-engine__oil { opacity: 0.5; }
.od-engine { width: 100%; height: auto; }

/* The galleries wash with oil when the drop lands. */
.od-engine__channel {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}
.od-engine__port { opacity: 0.85; }

.od-hero__impact {
  position: absolute;
  left: 50%;
  bottom: var(--od-port);
  width: 18px; height: 18px;
  margin: 0 0 -9px -9px;
  border-radius: 50%;
  border: 1px solid var(--od-oil-lit);
  opacity: 0;
}

.od-drop { display: block; }
.od-drop__art { width: 100%; height: auto; }

.od-drop--hero {
  position: absolute;
  left: 50%;
  bottom: var(--od-port);
  width: 30px;
  margin: 0 0 -12px -15px;
  opacity: 0;                       /* resolved: the drop is already inside */
}

.od-hero__copy {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center;
}
.od-hero__presents { color: var(--od-mute); justify-content: center; }

.od-hero__head {
  font-family: 'Archivo', 'Inter', sans-serif;
  font-weight: 800;
  font-size: clamp(2.1rem, 6.2vw, 4.2rem);
  line-height: 0.92;
  letter-spacing: -0.035em;
  color: var(--od-ink);
  margin-top: 1.15rem;
  display: flex; flex-direction: column; align-items: center;
}
.od-hero__head-2 { color: var(--od-blue-lit); }

.od-hero__what {
  margin-top: 1.5rem;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.8125rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--od-oil-lit);
}
.od-price--hero { margin-top: 0.55rem; }

.od-hero__when {
  margin-top: 1.2rem;
  font-size: clamp(1rem, 2.2vw, 1.2rem);
  font-weight: 600;
  color: var(--od-ink);
}
.od-hero__limits {
  margin-top: 0.35rem; font-size: 0.875rem; color: var(--od-mute);
  text-wrap: balance;
}

.od-hero__actions {
  margin-top: 1.9rem;
  display: flex; flex-wrap: wrap; gap: 0.85rem; justify-content: center;
}
.od-hero__next {
  margin-top: 1.4rem;
  display: flex; align-items: center; gap: 0.6rem;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.75rem; letter-spacing: 0.08em; color: var(--od-mute);
  justify-content: center; text-align: left;
}

.od-scrollcue {
  position: absolute; left: 50%; bottom: 1.6rem;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.625rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--od-faint);
  z-index: 3;
}
.od-scrollcue__rail {
  width: 1px; height: 42px;
  background: linear-gradient(to bottom, transparent, var(--od-blue-lit));
}

/* --------------------------------------------------------------------------
   THE JOURNEY — one line, one drop
   -------------------------------------------------------------------------- */
.od-journey { position: relative; }

.od-spine {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 0;
}
.od-spine__track {
  fill: none;
  stroke: var(--od-line-soft);
  stroke-width: 1.5;
  stroke-linecap: round;
}
.od-spine__flow {
  fill: none;
  stroke: var(--od-oil);
  stroke-width: 2.5;
  stroke-linecap: round;
  /* On cream a glow reads as a smudge, so the line is lifted with a soft cast
     shadow instead — the same trick the rest of the site uses. */
  filter: drop-shadow(0 1px 2px rgba(15, 37, 71, 0.22));
}

.od-drop--travel {
  position: absolute; top: 0; left: 0;
  width: 26px;
  margin: -18px 0 0 -13px;
  z-index: 3;
  display: none;                     /* resolved: nothing is in flight */
  filter: drop-shadow(0 2px 4px rgba(15, 37, 71, 0.28));
}

.od-anchor {
  position: absolute;
  width: 1px; height: 1px;
  pointer-events: none;
}
/* Where the oil leaves the engine: dead centre, exactly under the filler cap. */
.od-anchor--entry { top: 0; left: 50%; }

/* Guides carry no content and activate nothing. They exist so the line bows
   out around a centred headline instead of running straight through the type. */
.od-anchor--guide { top: 26%; }
.od-anchor--settle { top: 96px; left: 50%; }
/* The final approach: out around the closing copy, then back in to the button. */
.od-anchor--guide-cta { top: 30%; }
.od-anchor--guide-l { left: 9%; }
.od-anchor--guide-r { left: 91%; }

/* --------------------------------------------------------------------------
   Stops — shared layout
   -------------------------------------------------------------------------- */
.od-stop {
  position: relative;
  z-index: 1;
  padding-block: var(--od-section);
}
.od-stop__grid,
.od-stop__centre { position: relative; }

.od-stop__art { position: relative; }
.od-stop__art svg { width: 100%; height: auto; }
.od-art__cap {
  margin-top: 1.1rem;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6875rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--od-mute);
  display: flex; gap: 1.4rem; justify-content: center;
}

/* Copy that is not welded to the line still arrives, just gently. */
.od-r { opacity: 1; }

/* --------------------------------------------------------------------------
   STOP 01 — up to 5L
   -------------------------------------------------------------------------- */
.od-vial { --f: 1; }
/* 176 = the tube's interior height in _gauge.ejs. Translating the whole liquid
   group keeps the meniscus attached to the surface; scaling would flatten it
   into a progress bar. */
.od-vial__liquid {
  transform: translateY(calc((1 - var(--f)) * 176px));
  transform-box: view-box;
}
.od-vial__meniscus { opacity: calc(0.25 + 0.75 * var(--f)); }
.od-vial__num {
  fill: var(--od-oil-lit);
  opacity: calc(0.5 + 0.5 * var(--f));
}
.od-vial__body { transition: stroke-opacity var(--od-t) var(--od-ease); }

/* --------------------------------------------------------------------------
   STOP 02 — filter
   -------------------------------------------------------------------------- */
.od-filter__old {
  transform: translate(-28px, 26px) rotate(-9deg);
  transform-box: view-box;
  transform-origin: 82px 270px;
  opacity: 0.42;
}
.od-filter__new {
  transform: translate(-138px, -14px);
  transform-box: view-box;
  transform-origin: 358px 270px;
}
.od-art--filter .od-art__cap span { transition: color var(--od-t) var(--od-ease); }
.od-art--filter .od-art__cap-a,
.od-art--filter .od-art__cap-b { color: var(--od-ink-2); }
.od-art--filter .od-art__cap-c { color: var(--od-oil-lit); }
.od-filter__old { opacity: 0.42; }

/* --------------------------------------------------------------------------
   STOP 03 — the window
   -------------------------------------------------------------------------- */
.od-cluster__sweep { stroke-dashoffset: 0; }
.od-cluster__needle {
  transform: rotate(100deg);
  transform-box: view-box;
  transform-origin: 220px 232px;
}
.od-cluster__hour { opacity: 1; }

.od-bigday {
  font-family: 'Archivo', sans-serif;
  margin-bottom: clamp(-1rem, -1.5vw, -0.25rem);
  font-weight: 800;
  font-size: clamp(3.4rem, 15vw, 12rem);
  letter-spacing: -0.05em;
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(15, 37, 71, 0.12);
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  max-width: 100%;
}

.od-stop__centre { text-align: center; display: grid; justify-items: center; gap: 2.5rem; }
.od-stop__centre .od-eyebrow { justify-content: center; }
.od-stop__centre .od-body,
.od-stop__centre .od-lede,
.od-stop__centre .od-fine { margin-inline: auto; }
.od-stop__copy--under { display: grid; justify-items: center; gap: 0.9rem; }

/* --------------------------------------------------------------------------
   STOP 04 — limited bookings
   -------------------------------------------------------------------------- */
.od-slots__wrap { position: relative; width: 100%; display: flex; flex-direction: column; align-items: center; }
.od-slots {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.7rem;
  width: 100%;
  max-width: 760px;
  margin-inline: auto;
}
.od-slot {
  --reveal: 1;
  display: flex; flex-direction: column; gap: 0.3rem;
  padding: 0.95rem 0.9rem;
  border: 1px solid var(--od-steel);
  border-radius: 16px;
  background: var(--od-card);
  box-shadow: var(--od-shadow-sm);
  text-align: left;
  opacity: var(--reveal);
  transform: translateY(calc((1 - var(--reveal)) * 14px));
}
.od-slot__time {
  font-family: 'Archivo', sans-serif;
  font-size: 1.2rem; font-weight: 700; letter-spacing: -0.02em;
  color: var(--od-ink);
  font-variant-numeric: tabular-nums;
}
.od-slot__state {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.625rem; letter-spacing: 0.16em; text-transform: uppercase;
}
.od-slot.is-open { border-color: #BFD4F2; }
.od-slot.is-open .od-slot__state { color: var(--od-blue-lit); }
/* A taken slot recedes into the panel surface instead of the card surface. */
.od-slot.is-taken { background: var(--od-pit); box-shadow: none; }
.od-slot.is-taken .od-slot__time { color: var(--od-faint); text-decoration: line-through; text-decoration-thickness: 1px; }
.od-slot.is-taken .od-slot__state { color: var(--od-faint); }

.od-slots__note {
  margin-top: 1.4rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--od-mute);
  max-width: 52ch;
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   SCENE 5 — the line becomes the button
   -------------------------------------------------------------------------- */
.od-cta {
  position: relative;
  z-index: 1;
  padding-block: var(--od-section) clamp(5rem, 10vw, 8rem);
}
.od-cta__inner { position: relative; display: grid; justify-items: center; text-align: center; gap: 1.1rem; }
.od-cta__head { margin-top: 0.6rem; }
.od-cta__facts {
  display: grid; gap: 0.55rem;
  margin-top: 0.6rem;
  font-size: 0.9375rem;
  color: var(--od-ink-2);
  text-align: left;
}
.od-cta__facts li { display: flex; align-items: center; gap: 0.65rem; }
.od-cta__facts svg { color: var(--od-blue-lit); flex: none; }

.od-cta__button {
  position: relative;
  width: 100%;
  max-width: 480px;
  margin-top: 1.4rem;
  padding: 10px;                     /* room for the ring to sit outside the button */
}
.od-anchor--cta { top: 0; left: 50%; }

.od-cta__ring {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
}
.od-cta__ring-path {
  fill: none;
  stroke: var(--od-oil);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  filter: drop-shadow(0 1px 2px rgba(15, 37, 71, 0.20));
}

.od-cta__fine {
  margin-top: 0.8rem;
  font-size: 0.8125rem;
  color: var(--od-mute);
  max-width: 46ch;
}
.od-cta .od-btn--ghost { max-width: 480px; margin-top: 0.2rem; }

/* --------------------------------------------------------------------------
   Terms
   -------------------------------------------------------------------------- */
.od-terms { padding-block: clamp(2.5rem, 6vw, 4rem); border-top: 1px solid var(--od-line-soft); }
.od-terms__box { border: 1px solid var(--od-steel); border-radius: 16px; background: var(--od-pit); }
.od-terms__sum {
  cursor: pointer; list-style: none;
  padding: 1.15rem 1.4rem;
  min-height: 52px;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  font-size: 0.9375rem; font-weight: 600; color: var(--od-ink);
}
.od-terms__sum::-webkit-details-marker { display: none; }
.od-terms__sum::after {
  content: '+';
  font-family: 'JetBrains Mono', monospace;
  font-size: 1.15rem; color: var(--od-blue-lit); flex: none;
}
.od-terms__box[open] .od-terms__sum::after { content: '\2212'; }
.od-terms__body {
  padding: 0 1.4rem 1.5rem;
  display: grid; gap: 1rem;
  /* Legal copy is not microscopic on this page, on purpose. */
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--od-ink-2);
  max-width: 76ch;
}
.od-terms__body a { color: var(--od-blue-lit); }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.od-footer {
  border-top: 1px solid var(--od-line-soft);
  padding-block: 2.5rem;
  padding-bottom: calc(2.5rem + 5rem);   /* clears the sticky bar */
  font-size: 0.875rem;
  color: var(--od-mute);
}
.od-footer__row { display: flex; flex-wrap: wrap; gap: 1.6rem 2.5rem; justify-content: space-between; }
.od-footer__name { color: var(--od-ink); font-weight: 600; }
.od-footer a { color: inherit; text-decoration: none; }
.od-footer a:hover { color: var(--od-blue-lit); }
.od-footer__links { display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; align-items: flex-start; }
.od-footer__links a { min-height: 44px; display: inline-flex; align-items: center; }

/* --------------------------------------------------------------------------
   Sticky booking control
   -------------------------------------------------------------------------- */
.od-sticky {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: rgba(251, 250, 247, 0.93);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--od-steel);
  box-shadow: 0 -6px 20px -10px rgba(15, 37, 71, 0.25);
  padding: 0.65rem var(--od-gutter);
  padding-bottom: calc(0.65rem + env(safe-area-inset-bottom));
  transform: translateY(110%);
  transition: transform var(--od-t) var(--od-ease);
}
.od-sticky.is-shown { transform: translateY(0); }
.od-sticky__row {
  max-width: var(--od-max); margin-inline: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.od-sticky__meta { display: flex; flex-direction: column; line-height: 1.2; }
.od-sticky__when {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.6875rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--od-mute);
}
.od-sticky__price {
  font-family: 'Archivo', sans-serif;
  font-size: 1.25rem; font-weight: 700; letter-spacing: -0.02em; color: var(--od-ink);
}
.od-sticky__cta { min-width: 140px; }

/* ==========================================================================
   .od-motion — everything above, wound back to its start.
   Nothing below this line adds content; it only removes the finished state
   so the scroll can put it back.
   ========================================================================== */

.od-motion .od-stop,
.od-motion .od-cta { --sp: 0; }

/* ── The line ─────────────────────────────────────────────────────── */
.od-motion .od-drop--travel {
  display: block;
  opacity: 0;
  transition: opacity 260ms var(--od-ease);
}
.od-motion .od-drop--travel.is-flying { opacity: 1; }

/* ── STOP 01 — the five vessels fill in sequence ──────────────────── */
.od-motion .od-vial { --f: clamp(0, calc((var(--sp) - var(--vs)) / 0.2), 1); }
.od-motion [data-od-vial="0"] { --vs: 0.06; }
.od-motion [data-od-vial="1"] { --vs: 0.20; }
.od-motion [data-od-vial="2"] { --vs: 0.34; }
.od-motion [data-od-vial="3"] { --vs: 0.48; }
.od-motion [data-od-vial="4"] { --vs: 0.62; }
.od-motion .od-art--gauge .od-art__cap {
  opacity: clamp(0, calc((var(--sp) - 0.82) / 0.12), 1);
}

/* ── STOP 02 — remove, replace, ready ─────────────────────────────── */
.od-motion .od-filter__old {
  --o: clamp(0, calc((var(--sp) - 0.10) / 0.34), 1);
  transform: translate(calc(var(--o) * -28px), calc(var(--o) * 26px)) rotate(calc(var(--o) * -9deg));
  opacity: calc(1 - 0.58 * var(--o));
}
.od-motion .od-filter__new {
  --n: clamp(0, calc((var(--sp) - 0.44) / 0.40), 1);
  transform: translate(calc(var(--n) * -138px), calc(var(--n) * -14px));
}
.od-motion .od-art--filter .od-art__cap-a { opacity: clamp(0.3, calc(0.3 + (var(--sp) - 0.08) * 6), 1); }
.od-motion .od-art--filter .od-art__cap-b { opacity: clamp(0.3, calc(0.3 + (var(--sp) - 0.44) * 6), 1); }
.od-motion .od-art--filter .od-art__cap-c { opacity: clamp(0.3, calc(0.3 + (var(--sp) - 0.82) * 6), 1); }

/* ── STOP 03 — the needle wakes and sweeps 1 → 5 ──────────────────── */
.od-motion .od-cluster__sweep { stroke-dashoffset: calc(1 - var(--sp)); }
.od-motion .od-cluster__needle {
  transform: rotate(calc(-118deg + 218deg * var(--sp)));
}
.od-motion .od-cluster__hour { opacity: 0.28; }
.od-motion [data-od-hour="0"] { opacity: clamp(0.28, calc(0.28 + (var(--sp) - 0.02) * 24), 1); }
.od-motion [data-od-hour="1"] { opacity: clamp(0.28, calc(0.28 + (var(--sp) - 0.27) * 24), 1); }
.od-motion [data-od-hour="2"] { opacity: clamp(0.28, calc(0.28 + (var(--sp) - 0.52) * 24), 1); }
.od-motion [data-od-hour="3"] { opacity: clamp(0.28, calc(0.28 + (var(--sp) - 0.77) * 24), 1); }
.od-motion [data-od-hour="4"] { opacity: clamp(0.28, calc(0.28 + (var(--sp) - 0.96) * 24), 1); }

/* ── STOP 04 — the slots arrive as the oil passes ─────────────────── */
.od-motion .od-slot {
  --reveal: clamp(0, calc((var(--sp) - 0.12 - var(--i) * 0.055) / 0.2), 1);
  transition: border-color var(--od-t) var(--od-ease), background var(--od-t) var(--od-ease);
}
.od-motion .od-slots__note { opacity: clamp(0, calc((var(--sp) - 0.7) / 0.2), 1); }

/* ── SCENE 5 — the line closes into the button ─────────────────────
   The ring drawing itself around the button IS the payoff. The button is
   deliberately NOT animated from transparent to filled: a half-filled primary
   CTA is a low-contrast primary CTA, and a reader who stops scrolling mid
   transition would be left with one. It stays the finished blue button
   throughout and only blooms once the ring closes. */
.od-motion .od-cta__ring-path { stroke-dashoffset: calc(1 - var(--sp)); }
.od-motion .od-cta .od-btn--primary {
  transition: box-shadow 520ms var(--od-ease-out), background var(--od-t-fast) var(--od-ease);
}
.od-motion .od-cta.is-done .od-btn--primary {
  box-shadow: 0 0 0 2px rgba(192, 124, 30, 0.55), 0 14px 36px -12px rgba(15, 37, 71, 0.40);
}

/* ── Copy that is not on the line ─────────────────────────────────── */
.od-motion .od-r {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 620ms var(--od-ease-out), transform 620ms var(--od-ease-out);
}
.od-motion .od-r.is-in { opacity: 1; transform: none; }

/* ==========================================================================
   .od-play — the opening fall. Runs once per tab.
   The offer markup is complete from the first byte; this only delays its
   *paint*, and the price resolves at ~1.0s.
   ========================================================================== */
.od-play .od-drop--hero {
  opacity: 1;
  animation: odFall 1000ms var(--od-ease-oil) 140ms both;
}
@keyframes odFall {
  0%   { opacity: 0; transform: translateY(calc(-1 * var(--od-fall-dist))) scaleY(1); }
  12%  { opacity: 1; transform: translateY(calc(-0.88 * var(--od-fall-dist))) scaleY(1); }
  78%  { opacity: 1; transform: translateY(calc(-0.1 * var(--od-fall-dist))) scale(0.92, 1.22); }
  92%  { opacity: 1; transform: translateY(0) scale(1.1, 0.72); }
  100% { opacity: 0; transform: translateY(5px) scale(1.2, 0.46); }
}

.od-play .od-hero__impact { animation: odImpact 900ms var(--od-ease-out) 1080ms both; }
@keyframes odImpact {
  0%   { opacity: 0; transform: scale(0.3); }
  25%  { opacity: 0.9; }
  100% { opacity: 0; transform: scale(5.4); }
}

.od-play .od-engine__channel { animation: odWash 1500ms var(--od-ease) 1120ms both; }
@keyframes odWash {
  0%   { stroke-dashoffset: 1; opacity: 0; }
  18%  { opacity: 1; }
  70%  { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 0.45; }
}

.od-play .od-engine__port { animation: odPort 700ms var(--od-ease-out) 1080ms both; }
@keyframes odPort {
  0%   { opacity: 0; }
  100% { opacity: 0.85; }
}

/* The offer resolves as the drop lands. Ordered so the price is never last. */
.od-play .od-hero__copy > * { animation: odRise 700ms var(--od-ease-out) both; }
.od-play .od-hero__presents { animation-delay: 60ms; }
.od-play .od-hero__head    { animation-delay: 980ms; }
.od-play .od-hero__what    { animation-delay: 1020ms; }
.od-play .od-price--hero   { animation-delay: 1060ms; }
.od-play .od-hero__when    { animation-delay: 1220ms; }
.od-play .od-hero__limits  { animation-delay: 1280ms; }
.od-play .od-hero__actions { animation-delay: 1340ms; }
.od-play .od-hero__next    { animation-delay: 1440ms; }
@keyframes odRise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

.od-play .od-scrollcue { animation: odRise 700ms var(--od-ease-out) 1600ms both; }

/* ==========================================================================
   Responsive
   ========================================================================== */

/* ── Narrow: the line runs down a left rail, content sits beside it ── */
@media (max-width: 799px) {
  .od { --od-eng-w: min(520px, 116vw); --od-eng-bottom: 2.5rem; }

  /* Room for the line to leave the engine's centre and reach the rail. */
  .od-journey { padding-top: 3.5rem; }
  .od-anchor--settle { top: 104px; left: var(--od-rail); }

  /* The closing approach stays on the rail and hooks into the button at the
     end; the ring opens at that same landing point (see sizeCtaRing). */
  .od-anchor--guide-cta { left: var(--od-rail); top: 50%; }
  .od-anchor--cta { left: 12%; }

  /* The ghost word bleeds off the edge — but never mid-letter. */
  .od-bigday { font-size: clamp(2.9rem, 13vw, 12rem); }
  .od-stop { padding-block: clamp(4.5rem, 14vw, 7rem); }
  .od-stop__grid { display: grid; gap: 2.5rem; }

  /* Every anchor on the rail, so the path is a near-straight vertical.
     The art boxes go position:static so the anchors resolve against the
     full-width .od-stop — otherwise `left: 26px` would be 26px inside the
     artwork column rather than 26px from the edge of the page. */
  .od-stop__art, .od-slots__wrap { position: static; }
  .od-stop .od-anchor { left: var(--od-rail); top: 50%; }

  /* Content clears the rail. Scoped to the journey: the hero, terms and
     footer are not on the line and keep the ordinary gutter. */
  .od-journey .od-wrap { padding-left: calc(var(--od-rail) + 1.4rem); }

  .od-stop__centre { text-align: left; justify-items: start; gap: 2rem; }
  .od-stop__centre .od-eyebrow { justify-content: flex-start; }
  .od-stop__copy--under { justify-items: start; }
  .od-price--mid, .od-price--cta { justify-content: flex-start; }

  .od-bigday { left: auto; right: var(--od-gutter); transform: none; top: 0.5rem; }

  .od-art__cap { justify-content: flex-start; }
  .od-slots { grid-template-columns: repeat(2, 1fr); }

  .od-cta__inner { justify-items: start; text-align: left; }
  .od-cta__button, .od-cta .od-btn--ghost { max-width: none; }
  .od-price--cta { justify-content: center; }
  .od-cta__inner .od-price--cta { align-self: center; }
}

/* ── Wide: the line alternates between the artwork lanes ──────────── */
@media (min-width: 800px) {
  .od-stop__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(2.5rem, 6vw, 6rem);
    align-items: center;
  }
  .od-stop--right .od-stop__copy { order: 2; }
  .od-stop--right .od-stop__art  { order: 1; }

  /* Anchor sits at the centre of the artwork, so the line passes behind it. */
  .od-stop__art .od-anchor { left: 50%; top: 50%; }
  .od-slots__wrap .od-anchor { left: 50%; top: 50%; }

  .od-art--gauge, .od-art--cluster { max-width: 520px; margin-inline: auto; }
  .od-art--filter { max-width: 560px; margin-inline: auto; }
  .od-stop__centre .od-stop__art { width: min(520px, 100%); }
}

@media (min-width: 1100px) {
  .od-top__tel { font-size: 0.9375rem; }
}

/* Coarse pointers get no hover-only affordances, and the heaviest filters off. */
@media (hover: none) {
  .od-btn--primary:hover { background: var(--od-blue-deep); }
}
@media (max-width: 599px) {
  .od-spine__flow { filter: none; }
  .od-drop--travel { filter: none; }
  .od-cta__ring-path { filter: none; }
}

/* ==========================================================================
   Reduced motion
   The .od-motion class is never added, so the resolved state above is what
   renders. These rules only stop the few things that could still move.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .od *, .od *::before, .od *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
  .od-sticky { transition: none; }
}
