    /* ── Fonts (self-hosted, same .ttf files as the iOS bundle) ─────
       Replaces the previous Google Fonts CDN link so the web works
       offline after first load, matches the iOS-rendered look pixel-
       for-pixel, and lets us ship theme-specific display faces
       (Caveat for Postcard, Pacifico + Bubblegum Sans for Theme
       Park, Rye for Western) without an extra CDN trip. */
    @font-face { font-family: 'Outfit'; src: url('../fonts/Outfit-Light.ttf') format('truetype'); font-weight: 300; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Outfit'; src: url('../fonts/Outfit-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Outfit'; src: url('../fonts/Outfit-Medium.ttf') format('truetype'); font-weight: 500; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Outfit'; src: url('../fonts/Outfit-SemiBold.ttf') format('truetype'); font-weight: 600; font-style: normal; font-display: swap; }

    @font-face { font-family: 'DM Sans'; src: url('../fonts/DMSans-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
    @font-face { font-family: 'DM Sans'; src: url('../fonts/DMSans-Medium.ttf') format('truetype'); font-weight: 500; font-style: normal; font-display: swap; }

    @font-face { font-family: 'Playfair Display'; src: url('../fonts/PlayfairDisplay-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Playfair Display'; src: url('../fonts/PlayfairDisplay-SemiBold.ttf') format('truetype'); font-weight: 600; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Playfair Display'; src: url('../fonts/PlayfairDisplay-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }

    /* Theme-specific display faces — load only when the corresponding
       theme is active to avoid blocking initial render. */
    @font-face { font-family: 'Caveat'; src: url('../fonts/Caveat-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Caveat'; src: url('../fonts/Caveat-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Pacifico'; src: url('../fonts/Pacifico-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Bubblegum Sans'; src: url('../fonts/BubblegumSans-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Rye'; src: url('../fonts/Rye-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
    @font-face { font-family: 'Architects Daughter'; src: url('../fonts/ArchitectsDaughter-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }

    :root {
      /* Brand palette — matches iOS DesignSystem.swift exactly. */
      --color-midnight-grove: #0A1F14;
      --color-racing-green: #1A4D2E;
      --color-canopy: #2D6B45;
      --color-fern: #3E8A5C;
      --color-brass: #D4A64E;
      --color-autumn-ember: #C46B3A;
      --color-deep-moss: #1C2E26;
      --color-sage-mist: #7A8E84;
      --color-lichen: #E6EDE9;
      --color-morning-fog: #EFF4F1;
      --color-parchment: #FAF5EB;
      --color-ivory: #F8FAF9;
      --color-border: #B5C9BE;
      --color-border-light: #D4DDD8;
      --shadow: 0 4px 12px rgba(10, 31, 20, 0.10);
      --shadow-lg: 0 8px 24px rgba(10, 31, 20, 0.12);

      /* Postcard-theme palette — mirrors iOS so a trip switched
         from the iPhone Postcard theme renders the same hex on
         web. inkBlue specifically is the deep fountain-pen navy
         from the most recent iOS commit. */
      --color-ink-blue: #0F2649;
      --color-postmark-red: #8B3A2F;
      --color-tape-blue: #A6C8DC;
      --color-tape-pink: #E8B0B0;
      --color-tape-yellow: #E8D08E;
      --color-tape-green: #B5C9BE;

      /* Theme-Park palette — mirrors iOS DesignSystem.swift exactly so
         a trip switched between iPhone and web renders the same hex.
         The 6 accent colors cycle per-day; the cream is the card
         surface tint, the ink is the dark warm-brown body text, and
         the sage-wash is the translucent overlay on the map image
         that keeps text legible. */
      --color-park-cream: #FFF6E5;
      --color-park-ink: #3B2A1F;
      --color-park-sage-wash: #EDECEA;
      --color-park-ruby-red: #D24241;
      --color-park-royal-blue: #3B5BA7;
      --color-park-sunshine: #F0B233;
      --color-park-mint: #5FAE94;
      --color-park-navy: #1E3A5F;
      --color-park-racing-green: #0F4D33;
      --color-park-burnt-orange: #B14E2F;

      /* Magazine-theme editorial palette — 8 accents cycled per-day
         to give a multi-day trip a coordinated-feature feel.
         Mirrors iOS DesignSystem.swift exactly. */
      --color-editorial-navy: #1E3A5F;
      --color-editorial-burgundy: #7A2E3F;
      --color-editorial-ochre: #B8860B;
      --color-editorial-forest: #1F4733;
      --color-editorial-sienna: #C45A2B;
      --color-editorial-plum: #5D4F8C;
      --color-editorial-teal: #1F5765;
      --color-editorial-crimson: #9B2226;

      /* Mediterranean palette — sun-warmed plaster + 4 villa accents.
         Mirrors iOS DesignSystem.swift exactly. */
      --color-med-whitewash: #F4EFE6;
      --color-med-plaster-shadow: #E5DDD0;
      --color-med-terracotta-pale: #E8C9B3;
      --color-med-wrought-iron: #2A2620;
      --color-med-aegean-blue: #2D6E9F;
      --color-med-terracotta: #C66E47;
      --color-med-olive-grove: #6B7B47;
      --color-med-tuscan-ochre: #D9A35E;

      /* Ski Trip palette — alpine snow + 3 trail-difficulty accents
         (blue intermediate, green easy, black diamond). Mirrors iOS
         DesignSystem.swift exactly. */
      --color-ski-snow: #F7F9FB;
      --color-ski-glacier: #E2E8EE;
      --color-ski-midnight-pine: #1F2C3D;
      --color-ski-trail-blue: #1E5BA8;
      --color-ski-trail-green: #2E8B57;
      --color-ski-trail-diamond: #1A1A1A;

      /* Beach palette — cream towel + photographic sand + 4 pastel
         accents + the chunky cabana-stripe colors used on the top
         banner. Mirrors iOS DesignSystem.swift exactly. */
      --color-beach-towel-cream: #FCF8EC;
      --color-beach-towel-shadow: #E8DCBE;
      --color-beach-driftwood: #5A4A38;
      --color-beach-ocean-teal: #5BA89C;
      /* sunset-peach and coral-bloom are pulled darker than iOS for
         web — the lighter pastels don't pass as readable text on
         the cream wash with standard sRGB browser font rendering. */
      --color-beach-sunset-peach: #C97757;
      --color-beach-pale-sky: #A8C8D9;
      --color-beach-denim-blue: #5783A8;
      --color-beach-coral-bloom: #B85D40;

      /* Palm Beach Vibes palette — Lilly-preppy resort: warm-white
         lattice card, pastel-pink awning + gold trim, kelly-green
         lattice + activity icons. Mirrors iOS DesignSystem.swift (pb*). */
      --color-pb-lattice-white: #FBF8F0;
      --color-pb-club-navy: #1E2C4F;
      --color-pb-kelly-green: #1F7A4D;
      --color-pb-awning-pink: #F4B6C8;
      --color-pb-lilly-pink: #E64C82;
      --color-pb-citrus: #F0852B;
      --color-pb-pool-aqua: #36B5C4;
      --color-pb-brass: #B5862E;

      /* Mountain palette — WPA-poster cream + topographic-line tone +
         5 NP-poster accents. Mirrors iOS DesignSystem.swift exactly. */
      --color-mountain-paper: #F5EFE0;
      --color-mountain-topo: #BFA77E;
      --color-mountain-bark: #2D241B;
      --color-mountain-forest: #2D5239;
      --color-mountain-sky: #5B7FA1;
      --color-mountain-sunset: #C95A2C;
      --color-mountain-granite: #6E7378;
      --color-mountain-sage: #8A9C72;

      /* Western palette — aged ochre parchment + 5 desert accents.
         Mirrors iOS DesignSystem.swift exactly. */
      --color-western-parchment: #EFD9A9;
      --color-western-parchment-edge: #C8AA7A;
      --color-western-leather: #3B2415;
      --color-western-rust: #B5482A;
      --color-western-saddle: #8A5A2B;
      --color-western-sage: #7C8A5E;
      --color-western-ochre: #C68B33;
      --color-western-burgundy: #6B2433;

      /* Open Road palette — sun-bleached map cream + 4 American
         route accents (route-yellow / stop-red / coast-blue /
         desert-tan). Asphalt-black drives chrome + the highway
         banner strip. Mirrors iOS DesignSystem.swift exactly. */
      --color-road-cream: #EDE6D6;
      --color-road-cream-edge: #D6CDB5;
      --color-road-asphalt: #2A2A28;
      --color-road-highway-yellow: #F0BC2A;
      --color-road-stop-red: #C13B3B;
      --color-road-coast-blue: #3F77AB;
      --color-road-desert-tan: #C28D5E;
      --color-road-shield: #F5EFE0;

      /* Cotswolds palette — English countryside afternoon. Warm
         stone-paper card surface + 4 pastoral accents (hedgerow /
         rose / moss / thistle). Photo-bias map lives in JS.
         Mirrors iOS DesignSystem.swift exactly. */
      --color-cotswold-stone: #F2EBE0;
      --color-cotswold-stone-edge: #DCD4C4;
      --color-cotswold-ink: #3D352A;
      --color-cotswold-hedgerow: #3F5C3D;
      --color-cotswold-rose: #A35C5C;
      --color-cotswold-moss: #7A8C5E;
      --color-cotswold-thistle: #8B7AA3;
      --color-cotswold-honey: #B89456;

      /* Café au Lait palette — Parisian bistro: warm menu cream +
         deep chalkboard slate + 4 bistro accents (red / brass /
         cassis / jardin). Mirrors iOS DesignSystem.swift exactly. */
      --color-cafe-cream: #F4EBDD;
      --color-cafe-cream-edge: #DCD0BB;
      --color-cafe-chalkboard: #26302B;
      --color-cafe-chalk: #F4ECDC;
      --color-cafe-bistro-red: #A6353A;
      --color-cafe-brass: #B89456;
      --color-cafe-cassis: #6B3360;
      --color-cafe-jardin: #5A7A4F;
      --color-cafe-ink: #2A1F18;

      /* Tropical Jungle (Vintage Hawaii) palette — verdant rain-
         forest interior. Sun-cream paper + 4 canopy/hibiscus
         accents. Mirrors iOS DesignSystem.swift exactly. */
      --color-tropical-sun-cream: #FAF1DC;
      --color-tropical-mist-green: #DCE9CF;
      --color-tropical-bark: #4A2F1E;
      --color-tropical-canopy: #2F6041;
      --color-tropical-canopy-dark: #1B3A24;
      --color-tropical-fern: #5A8A4F;
      --color-tropical-hibiscus: #DD6B47;
      --color-tropical-amber: #9C6B0E;

      /* Tokyo Nights palette — STRUCTURALLY INVERTED: dark navy
         surface + 4 vapor-wave neon accents. Mirrors iOS exactly. */
      --color-tokyo-night: #0D1421;
      --color-tokyo-onyx: #0A0F18;
      --color-tokyo-asphalt: #1A2436;
      --color-tokyo-panel: #222D42;
      --color-tokyo-magenta: #FF2D87;
      --color-tokyo-cyan: #1AE5D9;
      --color-tokyo-electric: #7B5BFF;
      --color-tokyo-sakura: #FF85B5;
      --color-tokyo-bone: #E8EAF0;
      --color-tokyo-mist: #7C8CA0;

      /* ── Theme tokens (default = Modern) ──
         Day-card themes work by overriding these tokens via
         attribute selectors on <body data-theme="..."> below.
         Components reference --theme-* tokens; the underlying
         hex/font shifts when a theme swap fires. */
      --theme-day-card-bg: var(--color-ivory);
      --theme-day-card-border: var(--color-border-light);
      --theme-day-card-text: var(--color-deep-moss);
      --theme-day-card-text-muted: var(--color-sage-mist);
      --theme-day-card-accent: var(--color-racing-green);
      --theme-day-card-divider: var(--color-border-light);
      --theme-day-card-shadow: 0 2px 8px rgba(10, 31, 20, 0.06);

      /* Day-card typography — Modern uses the existing app fonts;
         themes override these to bring in script / display faces. */
      --theme-day-headline-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-headline-weight: 600;
      --theme-day-item-title-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-item-title-weight: 500;

      /* Banner — themes that want a decorative band above the
         day card content set --theme-banner-display: block + a
         background. Default Modern: hidden. */
      --theme-banner-display: none;
      --theme-banner-height: 0;
      --theme-banner-bg: transparent;
    }

    /* ── Theme picker (Settings → Appearance) ──
       Two-column grid of theme rows, each showing a 64×64
       preview swatch + name + tagline + a radio dot. Mirrors
       the iOS Settings appearance section. */
    .theme-picker {
      display: grid;
      grid-template-columns: 1fr;
      gap: 10px;
    }
    @media (min-width: 720px) {
      .theme-picker { grid-template-columns: 1fr 1fr; }
    }
    .theme-option {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 10px;
      background: var(--color-ivory);
      border: 1px solid var(--color-border-light);
      border-radius: 12px;
      cursor: pointer;
      transition: border-color 0.15s, background 0.15s;
    }
    .theme-option:hover { background: var(--color-morning-fog); }
    .theme-option.selected {
      border-color: var(--color-racing-green);
      border-width: 1.5px;
      background: rgba(26, 77, 46, 0.04);
    }
    .theme-swatch {
      width: 64px;
      height: 64px;
      border-radius: 8px;
      flex-shrink: 0;
      overflow: hidden;
      border: 1px solid var(--color-border-light);
      position: relative;
    }
    .theme-option-text { flex: 1; min-width: 0; }
    .theme-option-name {
      font-family: 'Outfit', 'Helvetica Neue', sans-serif;
      font-weight: 500;
      font-size: 0.95rem;
      color: var(--color-deep-moss);
    }
    .theme-option-tagline {
      font-size: 0.78rem;
      color: var(--color-sage-mist);
      margin-top: 2px;
    }
    .theme-option-check {
      width: 22px;
      height: 22px;
      border-radius: 50%;
      border: 1.5px solid var(--color-border);
      flex-shrink: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-size: 0.85rem;
    }
    .theme-option.selected .theme-option-check {
      border-color: var(--color-racing-green);
      background: var(--color-racing-green);
    }
    /* Swatch preview content — purely cosmetic miniatures of each
       theme's day card. Modern is just a cream card with a few
       capsule strokes; Postcard adds parchment + a Caveat date
       glimpse so the user can preview without selecting. */
    .theme-swatch.modern {
      background: var(--color-ivory);
    }
    .theme-swatch.modern::after {
      content: '';
      position: absolute;
      top: 8px;
      left: 8px;
      width: 28px;
      height: 4px;
      background: var(--color-deep-moss);
      border-radius: 2px;
      box-shadow:
        0 8px 0 -1px var(--color-lichen),
        0 14px 0 -1px var(--color-lichen);
    }
    .theme-swatch.postcard {
      background: var(--color-parchment);
    }
    .theme-swatch.postcard::before {
      content: 'June 5th';
      position: absolute;
      top: 22px;
      left: 8px;
      font-family: 'Caveat', serif;
      font-weight: 700;
      font-size: 18px;
      color: var(--color-ink-blue);
      transform: rotate(-2deg);
    }
    .theme-swatch.postcard::after {
      content: '';
      position: absolute;
      top: 6px;
      right: 6px;
      width: 12px;
      height: 16px;
      background: var(--color-brass);
      opacity: 0.6;
      border-radius: 1px;
    }
    /* Theme Park swatch — cream card, ruby-red banner stripe across
       the top with a tiny cream silhouette, and a small Pacifico
       date in the accent. */
    .theme-swatch.themePark {
      background: var(--color-park-cream);
      overflow: hidden;
    }
    .theme-swatch.themePark::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 14px;
      background: var(--color-park-ruby-red);
      background-image: url(/img/themepark-skyline-0.svg?v=20260430b);
      background-repeat: no-repeat;
      background-position: center bottom;
      background-size: 110% 100%;
    }
    .theme-swatch.themePark::after {
      content: 'June 5';
      position: absolute;
      bottom: 8px;
      left: 6px;
      font-family: 'Pacifico', cursive;
      font-size: 18px;
      color: var(--color-park-ruby-red);
      line-height: 1;
    }
    /* Magazine swatch — ivory card, navy hero block at the top with
       white "ISSUE 05" + Playfair "JUNE 5", 3px navy left rule. */
    .theme-swatch.magazine {
      background: var(--color-ivory);
      overflow: hidden;
    }
    .theme-swatch.magazine::before {
      content: 'JUNE 5';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 38px;
      background: var(--color-editorial-navy);
      color: #fff;
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 13px;
      display: flex;
      align-items: flex-end;
      justify-content: flex-start;
      padding: 0 0 4px 8px;
      letter-spacing: 0.5px;
    }
    .theme-swatch.magazine::after {
      content: '';
      position: absolute;
      left: 0; top: 0; bottom: 0;
      width: 3px;
      background: var(--color-editorial-navy);
    }
    /* Mediterranean swatch — whitewash card, mosaic stripe of 4 tiles
       at the top, Playfair "JUNE 5" date in Aegean blue. */
    .theme-swatch.mediterranean {
      background: var(--color-med-whitewash);
      overflow: hidden;
    }
    .theme-swatch.mediterranean::before {
      content: '';
      position: absolute;
      top: 6px; left: 6px; right: 6px;
      height: 6px;
      background: linear-gradient(
        to right,
        var(--color-med-aegean-blue) 0%, var(--color-med-aegean-blue) 25%,
        var(--color-med-terracotta) 25%, var(--color-med-terracotta) 50%,
        var(--color-med-olive-grove) 50%, var(--color-med-olive-grove) 75%,
        var(--color-med-tuscan-ochre) 75%, var(--color-med-tuscan-ochre) 100%
      );
      border-radius: 1px;
    }
    .theme-swatch.mediterranean::after {
      content: 'June 5';
      position: absolute;
      bottom: 8px;
      left: 8px;
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 16px;
      color: var(--color-med-wrought-iron);
      line-height: 1;
    }

    /* Palm Beach Vibes swatch — lattice-white card, a pastel-pink awning
       stripe with a gold line, and a Playfair "June 5" + flamingo. */
    .theme-swatch.palmBeach {
      background-color: var(--color-pb-lattice-white);
      background-image:
        repeating-linear-gradient(45deg, color-mix(in srgb, var(--color-pb-kelly-green) 16%, transparent) 0 1px, transparent 1px 9px),
        repeating-linear-gradient(-45deg, color-mix(in srgb, var(--color-pb-kelly-green) 16%, transparent) 0 1px, transparent 1px 9px);
      overflow: hidden;
    }
    .theme-swatch.palmBeach::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 12px;
      background:
        linear-gradient(var(--color-pb-brass), var(--color-pb-brass)) bottom / 100% 1.5px no-repeat,
        repeating-linear-gradient(to right,
          var(--color-pb-awning-pink) 0, var(--color-pb-awning-pink) calc(100% / 10),
          #FFFFFF calc(100% / 10), #FFFFFF calc(100% / 5));
    }
    .theme-swatch.palmBeach::after {
      content: 'June 5 🦩';
      position: absolute;
      bottom: 8px;
      left: 8px;
      font-family: 'Playfair Display', serif;
      font-weight: 600;
      font-size: 14px;
      color: var(--color-pb-club-navy);
      line-height: 1;
    }
    /* Ski Trip swatch — white snow card with a trail-blue mountain
       banner across the top + a small blue square trail badge. */
    .theme-swatch.skiTrip {
      background: #FFFFFF;
      overflow: hidden;
    }
    .theme-swatch.skiTrip::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 22px;
      background: var(--color-ski-trail-blue);
      background-image: url(/img/ski-mountains.svg?v=20260501a);
      background-size: 100% 100%;
      background-repeat: no-repeat;
    }
    .theme-swatch.skiTrip::after {
      content: '';
      position: absolute;
      bottom: 12px;
      left: 8px;
      width: 10px;
      height: 10px;
      background: var(--color-ski-trail-blue);
    }
    /* Beach swatch — cream towel card with a cabana-stripe header
       across the top + Outfit "June 5" date in driftwood. */
    .theme-swatch.beach {
      background: var(--color-beach-towel-cream);
      overflow: hidden;
    }
    .theme-swatch.beach::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 18px;
      background: linear-gradient(
        to bottom,
        var(--color-beach-pale-sky) 0,
        var(--color-beach-pale-sky) 5px,
        #FFFFFF 5px,
        #FFFFFF 7px,
        var(--color-beach-denim-blue) 7px,
        var(--color-beach-denim-blue) 12px,
        #FFFFFF 12px,
        #FFFFFF 14px,
        var(--color-beach-pale-sky) 14px,
        var(--color-beach-pale-sky) 18px
      );
    }
    .theme-swatch.beach::after {
      content: 'June 5';
      position: absolute;
      bottom: 8px;
      left: 8px;
      font-family: 'Outfit', sans-serif;
      font-weight: 300;
      font-size: 16px;
      letter-spacing: 0.5px;
      color: var(--color-beach-driftwood);
      line-height: 1;
    }
    /* Mountain swatch — cream poster card with a forest-green
       peak silhouette banner across the top + Playfair "JUN 5"
       date in mountain bark. */
    .theme-swatch.mountain {
      background: var(--color-mountain-paper);
      overflow: hidden;
    }
    .theme-swatch.mountain::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 16px;
      background-color: var(--color-mountain-forest);
      -webkit-mask-image: url(/img/mountain-peaks.svg);
      mask-image: url(/img/mountain-peaks.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
    }
    .theme-swatch.mountain::after {
      content: 'JUN 5';
      position: absolute;
      bottom: 8px;
      left: 8px;
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 14px;
      letter-spacing: 1px;
      color: var(--color-mountain-bark);
      line-height: 1;
    }
    /* Western swatch — aged parchment card with a rust barbed-wire
       banner across the top + Rye "June 5" date in rust. */
    .theme-swatch.western {
      background: var(--color-western-parchment);
      overflow: hidden;
    }
    .theme-swatch.western::before {
      content: '';
      position: absolute;
      top: 6px; left: 6px; right: 6px;
      height: 10px;
      background-color: var(--color-western-rust);
      -webkit-mask-image: url(/img/western-barbed-wire.svg);
      mask-image: url(/img/western-barbed-wire.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
    }
    .theme-swatch.western::after {
      content: 'June 5';
      position: absolute;
      bottom: 8px;
      left: 8px;
      font-family: 'Rye', serif;
      font-size: 14px;
      letter-spacing: 0.5px;
      color: var(--color-western-rust);
      line-height: 1;
    }

    /* Open Road swatch — sun-bleached cream paper with an asphalt
       strip + yellow center-line dashes at the top, chunky Outfit
       Black "JUN 5" date in asphalt below. */
    .theme-swatch.openRoad {
      background: var(--color-road-cream);
      overflow: hidden;
    }
    .theme-swatch.openRoad::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 11px;
      background:
        repeating-linear-gradient(
          to right,
          var(--color-road-highway-yellow) 0,
          var(--color-road-highway-yellow) 5px,
          transparent 5px,
          transparent 10px
        ) center / 100% 1.5px no-repeat,
        var(--color-road-asphalt);
    }
    .theme-swatch.openRoad::after {
      content: 'JUN 5';
      position: absolute;
      bottom: 6px;
      left: 8px;
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 13px;
      letter-spacing: 0.5px;
      color: var(--color-road-asphalt);
      line-height: 1;
      text-transform: uppercase;
    }

    /* Cotswolds swatch — stone paper with a tiny landscape photo
       banner across the top + Playfair italic "5 June" date in
       earthy ink below. */
    .theme-swatch.cotswolds {
      background: var(--color-cotswold-stone);
      overflow: hidden;
    }
    .theme-swatch.cotswolds::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 22px;
      background-image: url(/img/cotswolds-2.jpg);
      background-size: cover;
      background-position: center;
      background-repeat: no-repeat;
      box-shadow: inset 0 -1px 0 0 var(--color-cotswold-hedgerow);
    }
    .theme-swatch.cotswolds::after {
      content: '5 June';
      position: absolute;
      bottom: 6px;
      left: 8px;
      font-family: 'Playfair Display', serif;
      font-style: italic;
      font-size: 13px;
      letter-spacing: 0;
      color: var(--color-cotswold-ink);
      line-height: 1;
    }

    /* Café au Lait swatch — striped Parisian awning at the very
       top + a chalkboard band beneath with chalk "June 5". */
    .theme-swatch.cafeAuLait {
      background: var(--color-cafe-cream);
      overflow: hidden;
    }
    .theme-swatch.cafeAuLait::before {
      content: '';
      position: absolute;
      top: 0; left: 0; right: 0;
      height: 22px;
      background:
        linear-gradient(
          to bottom,
          transparent 0,
          transparent 4px,
          var(--color-cafe-chalkboard) 4px,
          var(--color-cafe-chalkboard) 100%
        ),
        repeating-linear-gradient(
          to right,
          var(--color-cafe-bistro-red) 0,
          var(--color-cafe-bistro-red) 6px,
          var(--color-cafe-cream) 6px,
          var(--color-cafe-cream) 12px
        );
    }
    .theme-swatch.cafeAuLait::after {
      content: 'June 5';
      position: absolute;
      top: 8px;
      left: 8px;
      font-family: 'Architects Daughter', cursive;
      font-size: 12px;
      letter-spacing: 0;
      color: var(--color-cafe-chalk);
      line-height: 1;
    }

    /* Vintage Hawaii swatch — sun-cream paper with a heavy cream
       wash over a tiny jungle photo, Playfair Bold "June 5" date. */
    .theme-swatch.tropicalJungle {
      background:
        linear-gradient(rgba(250, 241, 220, 0.85), rgba(250, 241, 220, 0.85)),
        url(/img/tropical-jungle-1.jpg);
      background-size: auto, cover;
      background-position: 0 0, center top;
      background-repeat: no-repeat, no-repeat;
      overflow: hidden;
    }
    .theme-swatch.tropicalJungle::before {
      content: 'TUE';
      position: absolute;
      top: 8px;
      left: 8px;
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 7px;
      letter-spacing: 1.5px;
      color: var(--color-tropical-amber);
      text-transform: uppercase;
      line-height: 1;
    }
    .theme-swatch.tropicalJungle::after {
      content: 'June 5';
      position: absolute;
      bottom: 8px;
      left: 8px;
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 13px;
      letter-spacing: 0;
      color: var(--color-tropical-bark);
      line-height: 1;
    }

    /* Tokyo Nights swatch — dark navy gradient with a glowing
       magenta "JUN 5" headline. */
    .theme-swatch.tokyoNights {
      background: linear-gradient(
        to bottom,
        var(--color-tokyo-asphalt) 0%,
        var(--color-tokyo-night) 60%,
        var(--color-tokyo-onyx) 100%
      );
      overflow: hidden;
    }
    .theme-swatch.tokyoNights::before {
      content: 'TUE';
      position: absolute;
      top: 8px;
      left: 8px;
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 7px;
      letter-spacing: 1.5px;
      color: var(--color-tokyo-magenta);
      text-transform: uppercase;
      line-height: 1;
    }
    .theme-swatch.tokyoNights::after {
      content: 'JUN 5';
      position: absolute;
      bottom: 8px;
      left: 8px;
      font-family: 'Outfit', sans-serif;
      font-weight: 800;
      font-size: 14px;
      letter-spacing: 1.5px;
      color: var(--color-tokyo-bone);
      line-height: 1;
      text-transform: uppercase;
      text-shadow:
        0 0 1px var(--color-tokyo-magenta),
        0 0 4px var(--color-tokyo-magenta),
        0 0 8px rgba(255, 45, 135, 0.5);
    }

    /* ── Postcard theme ──
       Cream parchment cards, deep fountain-pen navy ink, Caveat
       script headlines + item titles. iOS reference:
       PostcardDayCard.swift. */
    body[data-theme="postcard"] {
      --theme-day-card-bg: var(--color-parchment);
      --theme-day-card-border: rgba(15, 38, 73, 0.18);
      --theme-day-card-text: var(--color-ink-blue);
      --theme-day-card-text-muted: rgba(15, 38, 73, 0.55);
      --theme-day-card-accent: var(--color-ink-blue);
      --theme-day-card-divider: rgba(15, 38, 73, 0.25);
      --theme-day-card-shadow: 0 3px 10px rgba(15, 38, 73, 0.10);

      --theme-day-headline-font: 'Caveat', 'Playfair Display', serif;
      --theme-day-headline-weight: 700;
      --theme-day-item-title-font: 'Caveat', 'Playfair Display', serif;
      --theme-day-item-title-weight: 700;
    }

    /* Single-postcard layout — turn the whole .day-group into one
       parchment card with a postage stamp in the top-right and a
       handwritten sign-off at the bottom. Items stop being visually
       separate panels and become diary-style rows separated by
       dashed dividers, mirroring iOS PostcardDayCard.swift. */
    body[data-theme="postcard"] .day-group {
      position: relative;
      background: var(--color-parchment);
      border: 1px solid var(--theme-day-card-border);
      /* Inner double-line border — mirrors the iOS PostcardDayCard
         classic double-frame inset 8pt. `outline` doesn't take a
         pseudo so it's safe alongside our existing ::before stamp
         and ::after radial highlight. */
      outline: 1px solid rgba(15, 38, 73, 0.45);
      outline-offset: -10px;
      border-radius: 14px;
      padding: 18px 22px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    /* Faint warm radial highlight in the top-left — same brass-tinted
       wash the iOS day card has. Pure CSS, no extra DOM. */
    body[data-theme="postcard"] .day-group::after {
      content: '';
      position: absolute;
      inset: 0;
      background: radial-gradient(
        circle at top left,
        rgba(212, 166, 78, 0.10),
        transparent 60%
      );
      pointer-events: none;
      z-index: 0;
    }

    /* Bring all real content above the radial highlight. */
    body[data-theme="postcard"] .day-header,
    body[data-theme="postcard"] .day-items,
    body[data-theme="postcard"] .day-photos {
      position: relative;
      z-index: 1;
    }

    /* The header strip becomes the top of the postcard — no
       separate background, no border, just the date as handwritten
       script with a dashed underline. */
    body[data-theme="postcard"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 0 0 8px 0;
      /* Reserve space on the right so the date doesn't run under
         the postage stamp pinned to the top-right corner. */
      padding-right: 70px;
      align-items: flex-start;
    }
    body[data-theme="postcard"] .day-header:hover { filter: none; }

    /* Stacked Postcard header — weekday on top, big handwritten
       date below, location dek beneath. Mirrors iOS PostcardDayCard
       layout. The first span (containing date label + dek) becomes
       a vertical column. */
    body[data-theme="postcard"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 0;
    }
    body[data-theme="postcard"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="postcard"] .day-weekday {
      font-family: 'Caveat', 'Playfair Display', cursive;
      font-weight: 700;
      font-size: 1.55rem;
      color: var(--color-ink-blue);
      line-height: 1.0;
    }
    /* Suppress the inline-mode trailing comma on Postcard's stacked
       layout — the weekday and date already read as two lines. */
    body[data-theme="postcard"] .day-weekday::after {
      content: ',';
    }
    body[data-theme="postcard"] .day-date {
      font-family: 'Caveat', 'Playfair Display', cursive;
      font-weight: 700;
      font-size: 1.55rem;
      color: var(--color-ink-blue);
      line-height: 1.0;
      margin-top: 2px;
    }
    /* Reveal the dek line and show ONLY the location — no item
       count, no separator. The location is rendered as a smaller
       Caveat italic-feeling line beneath the date, mirroring the
       "Miami, FL, USA" line in iOS PostcardDayCard. */
    body[data-theme="postcard"] .day-dek {
      display: inline-block;
      font-family: 'Caveat', 'Playfair Display', cursive;
      font-weight: 400;
      font-size: 1.0rem;
      color: rgba(15, 38, 73, 0.7);
      margin-top: 4px;
      letter-spacing: 0;
      text-transform: none;
      font-style: normal;
    }
    body[data-theme="postcard"] .day-dek-sep,
    body[data-theme="postcard"] .day-dek-count {
      display: none;
    }

    /* Items lose their individual panel chrome and become diary
       rows separated by dashed ink-blue lines. */
    body[data-theme="postcard"] .day-items {
      padding-top: 0;
      border-top: 1px dashed var(--theme-day-card-divider);
      margin-top: 8px;
    }
    body[data-theme="postcard"] .itinerary-card {
      background: transparent;
      border: none;
      border-radius: 0;
      box-shadow: none;
      padding: 10px 0;
      margin-bottom: 0;
      border-bottom: 1px dashed var(--theme-day-card-divider);
    }
    body[data-theme="postcard"] .itinerary-card:last-child {
      border-bottom: none;
    }
    body[data-theme="postcard"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
    }

    /* Postage stamp — pinned to the top-right of the day group.
       Brass rectangle, slightly rotated, with a darker inner
       border ring + tiny "POST" text. Kept fully decorative
       (pointer-events: none) so taps pass through to the day
       header underneath. */
    body[data-theme="postcard"] .day-group::before {
      content: 'POST';
      position: absolute;
      top: 14px;
      right: 18px;
      width: 44px;
      height: 56px;
      background: var(--color-brass);
      color: rgba(15, 38, 73, 0.65);
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 0.6rem;
      letter-spacing: 1px;
      display: flex;
      align-items: flex-end;
      justify-content: center;
      padding-bottom: 4px;
      border-radius: 2px;
      box-shadow:
        inset 0 0 0 1px rgba(15, 38, 73, 0.35),
        inset 0 0 0 4px var(--color-brass),
        inset 0 0 0 5px rgba(15, 38, 73, 0.2);
      transform: rotate(4deg);
      pointer-events: none;
      z-index: 2;
    }

    /* Sign-off — "xoxo, Kintinery" at the bottom-right of the
       postcard. Hidden by default; only the postcard theme
       reveals it. The element is always rendered into the DOM
       so a theme switch shows/hides it without an itinerary
       re-render. */
    .day-postcard-signoff {
      display: none;
    }
    body[data-theme="postcard"] .day-postcard-signoff {
      display: block;
      font-family: 'Caveat', serif;
      font-weight: 700;
      font-size: 1.15rem;
      color: var(--color-ink-blue);
      opacity: 0.88;
      text-align: right;
      margin-top: 14px;
      padding-top: 4px;
      transform: rotate(-2deg);
      transform-origin: right center;
    }
    body[data-theme="postcard"] .day-postcard-signoff .signoff-greeting {
      opacity: 0.72;
      font-weight: 400;
      margin-right: 4px;
    }

    /* ── Postcard chrome — swap the default racing-green accent for
       ink-blue across FABs, tab strip, segmented controls, world clock
       strip, chat drawer header, and focus rings. Mirrors the per-theme
       chrome accent system on iOS (DayCardTheme.chromeAccent). */
    body[data-theme="postcard"] .tab-btn:hover { color: var(--color-ink-blue); }
    body[data-theme="postcard"] .tab-btn.active {
      color: var(--color-ink-blue);
      border-bottom-color: var(--color-ink-blue);
    }
    body[data-theme="postcard"] .view-btn.active {
      background: var(--color-ink-blue);
      color: #fff;
    }
    body[data-theme="postcard"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(15, 38, 73, 0.92) 0%, rgba(7, 22, 48, 0.92) 100%);
    }
    body[data-theme="postcard"] .chat-fab {
      background: linear-gradient(135deg, var(--color-ink-blue) 0%, #07162F 100%);
      box-shadow: 0 6px 20px rgba(15, 38, 73, 0.35);
    }
    body[data-theme="postcard"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(15, 38, 73, 0.5);
    }
    body[data-theme="postcard"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-ink-blue) 0%, #07162F 100%);
    }
    body[data-theme="postcard"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(15, 38, 73, 0.92) 0%, rgba(7, 22, 48, 0.92) 100%);
    }
    body[data-theme="postcard"] .clock-strip {
      background: var(--color-ink-blue);
    }
    body[data-theme="postcard"] .btn-upload {
      background: linear-gradient(135deg, var(--color-ink-blue) 0%, #07162F 100%);
    }
    body[data-theme="postcard"] .assignee-chip.selected {
      background: var(--color-ink-blue);
      border-color: var(--color-ink-blue);
      color: #fff;
    }
    body[data-theme="postcard"] :focus-visible {
      outline-color: var(--color-ink-blue);
    }
    /* Activity icons render as flat ink-blue glyphs without the
       coloured square plate. The default markup includes an inline
       `style="background: …"` from getItemColor(), so the override
       needs `!important` to win. */
    body[data-theme="postcard"] .item-icon {
      background: transparent !important;
      border-radius: 0;
      width: 28px;
      height: 28px;
    }
    body[data-theme="postcard"] .item-icon svg {
      color: var(--color-ink-blue);
      width: 22px;
      height: 22px;
      stroke-width: 2;
    }

    /* ─────────────────────────────────────────────────────────────────
       Theme Park theme
       ─────────────────────────────────────────────────────────────────
       Vintage hand-drawn park-map background under a sage-wash, top
       accent banner with cream park-skyline silhouettes, Pacifico
       script date, Bubblegum Sans item titles, ticket-stub type
       badges, spark-trail dividers. Per-day accent + map slice +
       skyline-variant are passed in via inline `--tp-accent`,
       `--tp-map`, `--tp-skyline` CSS variables on each `.day-group`
       (set in trip.js → themeParkDayLook()).

       Generic theme-park vocabulary only — no specific brand or
       trademarked imagery. iOS reference: ThemeParkDayCard.swift. */
    body[data-theme="themePark"] {
      --theme-day-card-bg: var(--color-park-cream);
      --theme-day-card-border: rgba(59, 42, 31, 0.18);
      --theme-day-card-text: var(--color-park-ink);
      --theme-day-card-text-muted: rgba(59, 42, 31, 0.55);
      --theme-day-card-accent: var(--color-park-navy);
      --theme-day-card-divider: rgba(59, 42, 31, 0.22);
      --theme-day-card-shadow: 0 3px 10px rgba(59, 42, 31, 0.12);

      --theme-day-headline-font: 'Pacifico', 'Playfair Display', cursive;
      --theme-day-headline-weight: 400;
      --theme-day-item-title-font: 'Bubblegum Sans', 'Outfit', sans-serif;
      --theme-day-item-title-weight: 400;
    }

    /* Day card — full-bleed park-map background image, sage-wash
       overlay (90% opacity matches iOS so the dark warm-brown text
       stays legible), subtle inner border. The map slice is paired
       1:1 with the day's accent so consecutive days walk both the
       palette and the map at once. */
    body[data-theme="themePark"] .day-group {
      position: relative;
      background-image: var(--tp-map);
      background-size: cover;
      background-position: center;
      background-color: var(--color-park-cream);
      border: 1px solid var(--theme-day-card-border);
      border-radius: 14px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
      padding: 0;
    }
    /* Sage wash on top of the map — flat translucent layer dimming
       the map enough for legible text but light enough that the
       hand-drawn illustration still reads. Web pulls the opacity
       matches iOS at 0.90 — the dark warm-brown text stays legible
       and the hand-drawn illustration shows through faintly as a
       texture rather than dominating the card. */
    body[data-theme="themePark"] .day-group::before {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--color-park-sage-wash);
      opacity: 0.90;
      pointer-events: none;
      z-index: 0;
    }
    /* Anything inside the day group needs a positive z-index so it
       paints on top of the wash layer. */
    body[data-theme="themePark"] .park-banner,
    body[data-theme="themePark"] .day-header,
    body[data-theme="themePark"] .day-items,
    body[data-theme="themePark"] .day-photos {
      position: relative;
      z-index: 1;
    }

    /* Accent banner — solid colored stripe across the very top of
       the card with a cream park-skyline silhouette layered on top
       (mask-image strategy: the SVG ships its own cream fill as
       background-image; the banner color shows through anywhere the
       SVG is transparent). 36px to mirror the iOS `frame(height: 36)`. */
    .park-banner { display: none; }
    body[data-theme="themePark"] .park-banner {
      display: block;
      height: 36px;
      background-color: var(--tp-accent);
      background-image: var(--tp-skyline);
      background-repeat: no-repeat;
      background-position: center bottom;
      background-size: 100% 100%;
    }
    /* Skyline variant URL is set per-day on .day-group via the inline
       `--tp-skyline` variable (see trip.js). The four variants are
       SVG files in /img bundling cream silhouettes of rides on a
       transparent ground line. */
    /* Absolute-from-root paths — these urls() are declared in
       /css/trip.css and would otherwise resolve relative to the
       stylesheet (i.e. /css/img/...) instead of the document root. */
    /* Cache-busting `?v=…` keeps the browser from showing the old
       filled-mountain coasters after we re-cut the SVGs to use
       stroked open tracks over visible support pillars. Bumped any
       time the SVG geometry changes. */
    body[data-theme="themePark"] .day-group[data-park-skyline="0"] { --tp-skyline: url(/img/themepark-skyline-0.svg?v=20260430b); }
    body[data-theme="themePark"] .day-group[data-park-skyline="1"] { --tp-skyline: url(/img/themepark-skyline-1.svg?v=20260430b); }
    body[data-theme="themePark"] .day-group[data-park-skyline="2"] { --tp-skyline: url(/img/themepark-skyline-2.svg?v=20260430b); }
    body[data-theme="themePark"] .day-group[data-park-skyline="3"] { --tp-skyline: url(/img/themepark-skyline-3.svg?v=20260430b); }

    /* Header — uppercase weekday eyebrow + Pacifico script date in
       the day's accent. `.day-header > span` is the existing markup
       that holds the date label + Today badge + weather; the script
       and color come from the theme-aware tokens. */
    body[data-theme="themePark"] .day-header {
      padding: 14px 20px 10px 20px;
      background: transparent;
      border: none;
    }
    body[data-theme="themePark"] .day-header > span:first-child {
      font-family: var(--theme-day-headline-font);
      font-weight: var(--theme-day-headline-weight);
      font-size: 1.85rem;
      color: var(--tp-accent);
      letter-spacing: 0;
      line-height: 1.1;
    }
    body[data-theme="themePark"] .day-toggle {
      color: rgba(59, 42, 31, 0.45);
    }

    /* Item rows — Bubblegum Sans titles in park ink, accent-tinted
       times. Items don't get the panel chrome the default theme has
       (the parchment-y day card serves as the panel); they just sit
       on the wash with thin spark-trail dividers between. */
    body[data-theme="themePark"] .day-items {
      padding: 4px 16px 16px 16px;
    }
    body[data-theme="themePark"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      padding: 10px 6px;
      margin-bottom: 0;
      border-radius: 0;
      position: relative;
    }
    body[data-theme="themePark"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(255, 246, 229, 0.35);
    }
    /* Spark-trail divider between items — three fading dots → thin
       accent line → small star-burst → thin accent line → three
       fading dots. Implemented as a single ::after pseudo using a
       layered background. Visual essence stand-in for the iOS
       FireworkBurst shape. */
    body[data-theme="themePark"] .itinerary-card + .itinerary-card::before {
      content: '';
      display: block;
      height: 10px;
      margin: 4px 0;
      background:
        radial-gradient(circle 1px at 14% 50%, var(--tp-accent) 60%, transparent 70%),
        radial-gradient(circle 1px at 22% 50%, color-mix(in srgb, var(--tp-accent) 60%, transparent) 60%, transparent 70%),
        radial-gradient(circle 1px at 30% 50%, color-mix(in srgb, var(--tp-accent) 35%, transparent) 60%, transparent 70%),
        radial-gradient(circle 1.5px at 50% 50%, var(--tp-accent) 60%, transparent 70%),
        radial-gradient(circle 1px at 70% 50%, color-mix(in srgb, var(--tp-accent) 35%, transparent) 60%, transparent 70%),
        radial-gradient(circle 1px at 78% 50%, color-mix(in srgb, var(--tp-accent) 60%, transparent) 60%, transparent 70%),
        radial-gradient(circle 1px at 86% 50%, var(--tp-accent) 60%, transparent 70%),
        linear-gradient(to right,
          transparent 4%,
          color-mix(in srgb, var(--tp-accent) 35%, transparent) 6%,
          color-mix(in srgb, var(--tp-accent) 35%, transparent) 44%,
          transparent 46%,
          transparent 54%,
          color-mix(in srgb, var(--tp-accent) 35%, transparent) 56%,
          color-mix(in srgb, var(--tp-accent) 35%, transparent) 94%,
          transparent 96%);
      background-repeat: no-repeat;
      background-position: center;
      background-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 0.5px;
    }

    body[data-theme="themePark"] .item-time {
      color: var(--tp-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      letter-spacing: 1.2px;
      text-transform: uppercase;
      font-size: 0.7rem;
    }
    body[data-theme="themePark"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.15rem;
      color: var(--color-park-ink);
    }

    /* Ticket-stub type badge — rounded rect with two semicircular
       notches on the left/right edges, like a punched amusement-park
       ticket. Built with `mask-image` so the ticket silhouette
       cleanly clips a tinted accent fill. The icon glyph sits on
       top in the day's accent. */
    body[data-theme="themePark"] .item-icon {
      background: transparent !important;
      border-radius: 0;
      width: 36px;
      height: 26px;
      position: relative;
    }
    body[data-theme="themePark"] .item-icon::before {
      content: '';
      position: absolute;
      inset: 0;
      background: color-mix(in srgb, var(--tp-accent) 18%, transparent);
      /* Ticket-stub silhouette: rounded rect with circular notches
         pulled out of the middle of each side. The mask uses two
         radial-gradients (the notches) plus a base linear-gradient
         (the rect) — when combined the inverted gradients carve out
         the notches. */
      -webkit-mask-image:
        radial-gradient(circle 4px at 0% 50%, transparent 99%, #000 100%),
        radial-gradient(circle 4px at 100% 50%, transparent 99%, #000 100%),
        linear-gradient(#000, #000);
      mask-image:
        radial-gradient(circle 4px at 0% 50%, transparent 99%, #000 100%),
        radial-gradient(circle 4px at 100% 50%, transparent 99%, #000 100%),
        linear-gradient(#000, #000);
      -webkit-mask-composite: source-in, source-in;
      mask-composite: intersect;
      border-radius: 6px;
    }
    body[data-theme="themePark"] .item-icon::after {
      content: '';
      position: absolute;
      inset: 0;
      pointer-events: none;
      border: 1px solid color-mix(in srgb, var(--tp-accent) 55%, transparent);
      border-radius: 6px;
      -webkit-mask-image:
        radial-gradient(circle 4px at 0% 50%, transparent 99%, #000 100%),
        radial-gradient(circle 4px at 100% 50%, transparent 99%, #000 100%),
        linear-gradient(#000, #000);
      mask-image:
        radial-gradient(circle 4px at 0% 50%, transparent 99%, #000 100%),
        radial-gradient(circle 4px at 100% 50%, transparent 99%, #000 100%),
        linear-gradient(#000, #000);
      -webkit-mask-composite: source-in, source-in;
      mask-composite: intersect;
    }
    body[data-theme="themePark"] .item-icon svg {
      color: var(--tp-accent);
      width: 18px;
      height: 18px;
      position: relative;
      z-index: 1;
    }

    /* Item detail section headers (Location / Confirmation / Notes) —
       small star + uppercase label in accent + accent underline. */
    body[data-theme="themePark"] .item-detail-section h4 {
      color: var(--tp-accent);
      font-family: 'Bubblegum Sans', sans-serif;
      letter-spacing: 1.2px;
      border-bottom: 1px solid color-mix(in srgb, var(--tp-accent) 35%, transparent);
      padding-bottom: 3px;
    }
    body[data-theme="themePark"] .item-detail-section h4::before {
      content: '★ ';
      color: var(--tp-accent);
    }

    /* Photos — 2px accent frame on each thumbnail, mirroring iOS. */
    body[data-theme="themePark"] .day-photos .day-photo {
      border: 2px solid var(--tp-accent);
      border-radius: 8px;
    }
    body[data-theme="themePark"] .day-photos {
      padding: 0 16px 16px 16px;
    }

    /* Theme Park chrome — FAB / clock-strip / picker / drawer accent
       all swap to parkNavy. World clock strip uses parkNavy as its
       dark slab (matching `darkClockStripBackground` on iOS). */
    body[data-theme="themePark"] .tab-btn:hover { color: var(--color-park-navy); }
    body[data-theme="themePark"] .tab-btn.active {
      color: var(--color-park-navy);
      border-bottom-color: var(--color-park-navy);
    }
    body[data-theme="themePark"] .view-btn.active {
      background: var(--color-park-navy);
      color: #fff;
    }
    body[data-theme="themePark"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(30, 58, 95, 0.92) 0%, rgba(15, 30, 50, 0.92) 100%);
    }
    body[data-theme="themePark"] .chat-fab {
      background: linear-gradient(135deg, var(--color-park-navy) 0%, #0F1E32 100%);
      box-shadow: 0 6px 20px rgba(30, 58, 95, 0.35);
    }
    body[data-theme="themePark"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(30, 58, 95, 0.5);
    }
    body[data-theme="themePark"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-park-navy) 0%, #0F1E32 100%);
    }
    body[data-theme="themePark"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(30, 58, 95, 0.92) 0%, rgba(15, 30, 50, 0.92) 100%);
    }
    body[data-theme="themePark"] .clock-strip {
      background: var(--color-park-navy);
    }
    body[data-theme="themePark"] .btn-upload {
      background: linear-gradient(135deg, var(--color-park-navy) 0%, #0F1E32 100%);
    }
    body[data-theme="themePark"] .assignee-chip.selected {
      background: var(--color-park-navy);
      border-color: var(--color-park-navy);
      color: #fff;
    }
    body[data-theme="themePark"] :focus-visible {
      outline-color: var(--color-park-navy);
    }

    /* ─────────────────────────────────────────────────────────────────
       Magazine theme
       ─────────────────────────────────────────────────────────────────
       Editorial travel-magazine spread — full-bleed hero photo at
       the top of each day card (or solid accent block when there's
       no photo yet) with an "Issue NN" eyebrow + giant Playfair
       date headline overlaid; ivory card body; 3px accent rule on
       the LEFT edge running the card's full height; small-caps
       weekday eyebrow; italic "dek" line for location + agenda
       count; drop-cap on the first item title; pull-quote treatment
       on confirmation codes. Per-day accent is selected from 8
       editorial colors via days_since_epoch % 8 (set in trip.js →
       magazineDayLook()) and surfaced as `--mag-accent`.

       iOS reference: MagazineDayCard.swift. */
    body[data-theme="magazine"] {
      --theme-day-card-bg: var(--color-ivory);
      --theme-day-card-border: var(--color-border-light);
      --theme-day-card-text: var(--color-deep-moss);
      --theme-day-card-text-muted: var(--color-sage-mist);
      --theme-day-card-accent: var(--color-editorial-navy);
      --theme-day-card-divider: var(--color-border-light);
      --theme-day-card-shadow: 0 3px 10px rgba(10, 31, 20, 0.08);

      --theme-day-headline-font: 'Playfair Display', 'Georgia', serif;
      --theme-day-headline-weight: 700;
      --theme-day-item-title-font: 'Playfair Display', 'Georgia', serif;
      --theme-day-item-title-weight: 600;
    }

    /* Day-group becomes the magazine "page" — ivory with a 3px
       accent rule on the left edge and a soft shadow lifting it off
       the page. Hides the .day-group margin so the rule runs
       edge-to-edge top-to-bottom. */
    body[data-theme="magazine"] .day-group {
      position: relative;
      background: var(--color-ivory);
      border-radius: 12px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }
    /* Left accent rule — full height, 3px wide. ::after is unused on
       day-group in this theme, so we co-opt it. */
    body[data-theme="magazine"] .day-group::after {
      content: '';
      position: absolute;
      left: 0; top: 0; bottom: 0;
      width: 3px;
      background: var(--mag-accent);
      pointer-events: none;
      z-index: 2;
    }

    /* Hero — 180px tall, full-bleed image (or solid accent block).
       Hidden on every other theme. The element ships with a
       gradient overlay + corner-positioned "Issue NN" eyebrow + a
       giant Playfair date headline. */
    .mag-hero { display: none; }
    body[data-theme="magazine"] .mag-hero {
      display: block;
      position: relative;
      height: 180px;
      background-color: var(--mag-accent);
      background-image: var(--mag-hero);
      background-size: cover;
      background-position: center;
      background-repeat: no-repeat;
      cursor: pointer;
    }
    /* Editorial gradient — dark at the bottom so the overlay text
       reads cleanly on any photo. Skipped (visually) when there's
       no photo because the accent block is already dark enough,
       but cheap to leave on always. */
    body[data-theme="magazine"] .mag-hero::before {
      content: '';
      position: absolute;
      inset: 0;
      background: linear-gradient(
        to bottom,
        rgba(0, 0, 0, 0) 50%,
        rgba(0, 0, 0, 0.55) 100%
      );
      pointer-events: none;
    }
    /* Subtle radial highlight on the accent block so empty days have
       a touch of dimensionality. Opacity is low so it disappears
       under any real photo. */
    body[data-theme="magazine"] .mag-hero::after {
      content: '';
      position: absolute;
      inset: 0;
      background: radial-gradient(
        ellipse at top left,
        rgba(255, 255, 255, 0.10),
        rgba(255, 255, 255, 0) 60%
      );
      pointer-events: none;
    }

    body[data-theme="magazine"] .mag-hero-overlay {
      position: absolute;
      left: 24px;
      bottom: 16px;
      right: 24px;
      z-index: 1;
      pointer-events: none;
    }
    body[data-theme="magazine"] .mag-hero-issue {
      font-family: 'DM Sans', sans-serif;
      font-size: 0.65rem;
      font-weight: 500;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: rgba(255, 255, 255, 0.85);
      margin-bottom: 4px;
    }
    body[data-theme="magazine"] .mag-hero-headline {
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 1.85rem;
      color: #fff;
      line-height: 1.05;
      text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
    }

    /* Header — the existing day-header strip below the hero.
       Replace its surface so the eyebrow + dek read on ivory. The
       date already appears in the hero overlay so we hide the
       header's date label and show only the chevron + weather. */
    body[data-theme="magazine"] .day-header {
      background: var(--color-ivory);
      border: none;
      border-radius: 0;
      padding: 14px 24px;
      font-family: 'DM Sans', sans-serif;
      font-weight: 500;
      font-size: 0.7rem;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: var(--mag-accent);
    }
    /* Hide the long-form date label inside the header (it's already
       in the hero overlay) — keep the toggle chevron + weather
       badge visible. The Today badge inside the span is also
       hidden, but the weather badge floats outside the date label
       text node so it survives. */
    body[data-theme="magazine"] .day-header > span:first-child {
      visibility: hidden;
      position: relative;
    }
    /* Weather badge inside the header IS visible — it's wrapped in
       its own .day-weather span. Pull it back out by undoing the
       parent visibility on it. */
    body[data-theme="magazine"] .day-header .day-weather {
      visibility: visible;
      position: absolute;
      left: 24px;
      top: 50%;
      transform: translateY(-50%);
    }

    /* Item rows — Playfair Display titles, accent-tinted small-caps
       times. Drops the panel chrome so items read as a clean
       editorial list rather than separate boxes. Confirmation codes
       get a left-bar pull-quote treatment (handled below via the
       generic .item-detail-section rule). */
    body[data-theme="magazine"] .day-items {
      padding: 12px 24px 20px 24px;
    }
    body[data-theme="magazine"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 12px 0;
      margin-bottom: 0;
      border-bottom: 1px solid var(--color-border-light);
    }
    body[data-theme="magazine"] .itinerary-card:last-child {
      border-bottom: none;
    }
    body[data-theme="magazine"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(184, 134, 11, 0.03);
    }

    body[data-theme="magazine"] .item-time {
      color: var(--mag-accent);
      font-family: 'DM Sans', sans-serif;
      font-weight: 500;
      font-size: 0.65rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      opacity: 0.85;
    }
    body[data-theme="magazine"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.25rem;
      color: var(--color-deep-moss);
      line-height: 1.2;
    }
    /* Drop-cap on the FIRST item's title — giant first letter in
       the day's accent. The CSS `::first-letter` pseudo handles the
       inline flow naturally so the rest of the title wraps below. */
    body[data-theme="magazine"] .day-items .itinerary-card:first-child .item-title::first-letter {
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 2.4rem;
      color: var(--mag-accent);
      float: left;
      line-height: 0.85;
      padding-right: 6px;
      padding-top: 4px;
    }

    /* Item icon — magazine drops the colored type plate; just a
       small accent-tinted glyph next to the title. */
    body[data-theme="magazine"] .item-icon {
      background: transparent !important;
      border-radius: 0;
      width: 28px;
      height: 28px;
    }
    body[data-theme="magazine"] .item-icon svg {
      color: var(--mag-accent);
      width: 18px;
      height: 18px;
      stroke-width: 1.8;
    }

    /* Detail sections — small-caps Playfair labels in accent +
       hairline accent underline. */
    body[data-theme="magazine"] .item-detail-section h4 {
      color: var(--mag-accent);
      font-family: 'DM Sans', sans-serif;
      font-weight: 500;
      font-size: 0.65rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      border-bottom: 1px solid color-mix(in srgb, var(--mag-accent) 30%, transparent);
      padding-bottom: 3px;
    }

    /* Photo grid — clean rounded-rect thumbs with no extra frame. */
    body[data-theme="magazine"] .day-photos {
      padding: 0 24px 20px 24px;
    }

    /* Magazine chrome — FAB / picker / clock-strip / drawer accent
       all swap to editorialNavy. World clock strip uses
       editorialNavy as its dark slab (matches `darkClockStripBackground`
       on iOS). */
    body[data-theme="magazine"] .tab-btn:hover { color: var(--color-editorial-navy); }
    body[data-theme="magazine"] .tab-btn.active {
      color: var(--color-editorial-navy);
      border-bottom-color: var(--color-editorial-navy);
    }
    body[data-theme="magazine"] .view-btn.active {
      background: var(--color-editorial-navy);
      color: #fff;
    }
    body[data-theme="magazine"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(30, 58, 95, 0.92) 0%, rgba(15, 30, 50, 0.92) 100%);
    }
    body[data-theme="magazine"] .chat-fab {
      background: linear-gradient(135deg, var(--color-editorial-navy) 0%, #0F1E32 100%);
      box-shadow: 0 6px 20px rgba(30, 58, 95, 0.35);
    }
    body[data-theme="magazine"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(30, 58, 95, 0.5);
    }
    body[data-theme="magazine"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-editorial-navy) 0%, #0F1E32 100%);
    }
    body[data-theme="magazine"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(30, 58, 95, 0.92) 0%, rgba(15, 30, 50, 0.92) 100%);
    }
    body[data-theme="magazine"] .clock-strip {
      background: var(--color-editorial-navy);
    }
    body[data-theme="magazine"] .btn-upload {
      background: linear-gradient(135deg, var(--color-editorial-navy) 0%, #0F1E32 100%);
    }
    body[data-theme="magazine"] .assignee-chip.selected {
      background: var(--color-editorial-navy);
      border-color: var(--color-editorial-navy);
      color: #fff;
    }
    body[data-theme="magazine"] :focus-visible {
      outline-color: var(--color-editorial-navy);
    }

    /* ─────────────────────────────────────────────────────────────────
       Mediterranean theme
       ─────────────────────────────────────────────────────────────────
       Sun-warmed whitewash plaster surface, 8-tile mosaic banner
       across the top, Playfair serif date headline with a tilted
       olive-leaf glyph, azulejo-style tile badges on items,
       mini-mosaic dividers between rows, 3px accent ceramic frame
       on photos with a 2×2 mosaic corner. Per-day accent rotates
       through 4 villa colors (Aegean / terracotta / olive grove /
       Tuscan ochre) via days_since_epoch % 4, surfaced as
       `--med-accent` and `--med-neighbor` (the +2 palette neighbor,
       used for dividers + the alternating mosaic-corner tile).

       iOS reference: MediterraneanDayCard.swift. */
    body[data-theme="mediterranean"] {
      --theme-day-card-bg: var(--color-med-whitewash);
      --theme-day-card-border: var(--color-med-plaster-shadow);
      --theme-day-card-text: var(--color-med-wrought-iron);
      --theme-day-card-text-muted: rgba(42, 38, 32, 0.55);
      --theme-day-card-accent: var(--color-med-aegean-blue);
      --theme-day-card-divider: rgba(42, 38, 32, 0.12);
      --theme-day-card-shadow: 0 3px 10px rgba(42, 38, 32, 0.10);

      --theme-day-headline-font: 'Playfair Display', 'Georgia', serif;
      --theme-day-headline-weight: 700;
      --theme-day-item-title-font: 'Playfair Display', 'Georgia', serif;
      --theme-day-item-title-weight: 600;
    }

    /* Day card — whitewash plaster surface with a soft sun-bleach
       radial highlight in the top-left, recessed inset border. The
       inset border is drawn via `outline` with negative offset so
       it doesn't conflict with the mosaic banner. */
    body[data-theme="mediterranean"] .day-group {
      position: relative;
      background:
        radial-gradient(
          ellipse at top left,
          rgba(255, 255, 255, 0.5),
          rgba(255, 255, 255, 0) 50%
        ),
        var(--color-med-whitewash);
      border: 1px solid var(--color-med-plaster-shadow);
      border-radius: 14px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
      outline: 1px solid var(--color-med-plaster-shadow);
      outline-offset: -8px;
    }

    /* Mosaic banner — 8 small accent-tinted tiles forming an
       architectural strip. JS renders the spans with explicit
       background colors so the same CSS rule lays them out for any
       per-day pattern. Hidden on every theme except mediterranean. */
    .med-banner { display: none; }
    body[data-theme="mediterranean"] .med-banner {
      display: flex;
      gap: 3px;
      padding: 10px 12px 6px 12px;
      position: relative;
      z-index: 1;
    }
    body[data-theme="mediterranean"] .med-banner span {
      flex: 1 1 0;
      height: 10px;
      border-radius: 1.5px;
    }

    /* Header — weekday eyebrow in accent + Playfair date headline +
       olive-leaf glyph + italic dek. Pulls the recessed inset
       border up so it frames the content rather than the card edge. */
    body[data-theme="mediterranean"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 8px 18px 10px 18px;
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 1.4rem;
      color: var(--color-med-wrought-iron);
      position: relative;
      z-index: 1;
    }
    /* Olive-leaf glyph — UTF-8 "🌿" pinned to the right side of
       the header just left of the toggle chevron, so it sits
       opposite the date. Absolute positioning keeps it out of the
       flex flow so it doesn't push the date span around. */
    body[data-theme="mediterranean"] .day-header::after {
      content: '🌿';
      position: absolute;
      right: 40px;
      top: 50%;
      transform: translateY(-50%) rotate(-20deg);
      font-size: 1rem;
      pointer-events: none;
    }
    body[data-theme="mediterranean"] .day-toggle {
      color: rgba(42, 38, 32, 0.4);
    }

    /* Items — tile-shaped badges, Playfair titles, mini-mosaic
       dividers between rows, accent-tinted small-caps times. */
    body[data-theme="mediterranean"] .day-items {
      padding: 4px 18px 16px 18px;
      position: relative;
      z-index: 1;
    }
    body[data-theme="mediterranean"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="mediterranean"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(42, 38, 32, 0.03);
    }
    /* Mini-mosaic divider between items — repeating accent +
       neighbor squares centered with airy gaps. Visual essence
       stand-in for iOS `miniMosaicDivider`.
       `.itinerary-card` is `display: flex`, so a pseudo on the
       card flows into its row as a flex child (sitting to the
       LEFT of the icon). Lifting it out of the flow with absolute
       positioning + a top offset that pokes into the previous
       card's bottom margin gives the right "between rows" feel. */
    body[data-theme="mediterranean"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: -6px;
      left: 50%;
      transform: translateX(-50%);
      height: 8px;
      width: 78px;
      background: repeating-linear-gradient(
        to right,
        var(--med-accent) 0px,
        var(--med-accent) 8px,
        transparent 8px,
        transparent 12px,
        var(--med-neighbor) 12px,
        var(--med-neighbor) 20px,
        transparent 20px,
        transparent 24px
      );
      opacity: 0.7;
      border-radius: 1px;
      pointer-events: none;
    }
    /* Add headroom on rows that follow another row so the
       absolutely-positioned divider has space to sit in. */
    body[data-theme="mediterranean"] .itinerary-card + .itinerary-card {
      margin-top: 10px;
    }

    body[data-theme="mediterranean"] .item-time {
      color: var(--med-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.7rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }
    body[data-theme="mediterranean"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.1rem;
      color: var(--color-med-wrought-iron);
      line-height: 1.25;
    }

    /* Azulejo tile badge — 28×28 rounded-rect (small radius), accent
       fill at low opacity, accent border, accent icon glyph.
       Replaces the colored square plate from the default theme. */
    body[data-theme="mediterranean"] .item-icon {
      background: transparent !important;
      border: 1px solid color-mix(in srgb, var(--med-accent) 55%, transparent);
      background-color: color-mix(in srgb, var(--med-accent) 18%, transparent) !important;
      border-radius: 2px;
      width: 28px;
      height: 28px;
    }
    body[data-theme="mediterranean"] .item-icon svg {
      color: var(--med-accent);
      width: 16px;
      height: 16px;
      stroke-width: 1.8;
    }

    /* Detail section headers — small-caps tracked in accent + thin
       accent underline. */
    body[data-theme="mediterranean"] .item-detail-section h4 {
      color: var(--med-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.65rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      border-bottom: 1px solid color-mix(in srgb, var(--med-accent) 30%, transparent);
      padding-bottom: 3px;
    }

    /* Photos — 3-up grid with 3px accent ceramic frame and a tiny
       2×2 mosaic corner in the top-left. */
    body[data-theme="mediterranean"] .day-photos {
      padding: 0 18px 16px 18px;
      position: relative;
      z-index: 1;
    }
    body[data-theme="mediterranean"] .day-photos .day-photo-thumb,
    body[data-theme="mediterranean"] .day-photos .day-photo {
      border: 3px solid var(--med-accent);
      border-radius: 4px;
      position: relative;
    }
    /* 2×2 mosaic corner — 4 tiny tiles in alternating accent /
       neighbor colors. Drawn as a CSS conic-gradient mosaic in a
       small absolutely-positioned ::after on the thumb wrapper. */
    body[data-theme="mediterranean"] .day-photos .day-photo-thumb::after {
      content: '';
      position: absolute;
      top: 4px;
      left: 4px;
      width: 10px;
      height: 10px;
      background:
        linear-gradient(to right,
          var(--med-accent) 0%, var(--med-accent) 50%,
          var(--med-neighbor) 50%, var(--med-neighbor) 100%) top / 100% 50% no-repeat,
        linear-gradient(to right,
          var(--med-neighbor) 0%, var(--med-neighbor) 50%,
          var(--med-accent) 50%, var(--med-accent) 100%) bottom / 100% 50% no-repeat;
      pointer-events: none;
    }

    /* Mediterranean chrome — Aegean blue across FAB / picker /
       clock-strip / drawer / focus ring. Matches iOS
       `darkClockStripBackground = .medAegeanBlue`. */
    body[data-theme="mediterranean"] .tab-btn:hover { color: var(--color-med-aegean-blue); }
    body[data-theme="mediterranean"] .tab-btn.active {
      color: var(--color-med-aegean-blue);
      border-bottom-color: var(--color-med-aegean-blue);
    }
    body[data-theme="mediterranean"] .view-btn.active {
      background: var(--color-med-aegean-blue);
      color: #fff;
    }
    body[data-theme="mediterranean"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(45, 110, 159, 0.92) 0%, rgba(28, 75, 110, 0.92) 100%);
    }
    body[data-theme="mediterranean"] .chat-fab {
      background: linear-gradient(135deg, var(--color-med-aegean-blue) 0%, #1C4B6E 100%);
      box-shadow: 0 6px 20px rgba(45, 110, 159, 0.35);
    }
    body[data-theme="mediterranean"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(45, 110, 159, 0.5);
    }
    body[data-theme="mediterranean"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-med-aegean-blue) 0%, #1C4B6E 100%);
    }
    body[data-theme="mediterranean"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(45, 110, 159, 0.92) 0%, rgba(28, 75, 110, 0.92) 100%);
    }
    body[data-theme="mediterranean"] .clock-strip {
      background: var(--color-med-aegean-blue);
    }
    body[data-theme="mediterranean"] .btn-upload {
      background: linear-gradient(135deg, var(--color-med-aegean-blue) 0%, #1C4B6E 100%);
    }
    body[data-theme="mediterranean"] .assignee-chip.selected {
      background: var(--color-med-aegean-blue);
      border-color: var(--color-med-aegean-blue);
      color: #fff;
    }
    body[data-theme="mediterranean"] :focus-visible {
      outline-color: var(--color-med-aegean-blue);
    }

    /* ─────────────────────────────────────────────────────────────────
       Ski Trip theme
       ─────────────────────────────────────────────────────────────────
       Crisp alpine snow surface with a 56px mountain-silhouette banner
       at the top of every card (sky tinted in the day's accent + back
       and front mountain ranges + white snow caps + scattered flurries).
       Items wear trail-difficulty shape badges — blue square
       (intermediate), green circle (easy), black diamond (expert) —
       cycled by the day's position within the trip (NOT calendar
       date) so day 1 is always the blue-square day, harmonizing
       with the navy world-clock strip above. Snowflake-glyph
       dividers replace the line-based dividers of other themes.

       iOS reference: SkiTripDayCard.swift. */
    body[data-theme="skiTrip"] {
      --theme-day-card-bg: #FFFFFF;
      --theme-day-card-border: var(--color-ski-glacier);
      --theme-day-card-text: var(--color-ski-midnight-pine);
      --theme-day-card-text-muted: rgba(31, 44, 61, 0.55);
      --theme-day-card-accent: var(--color-ski-trail-blue);
      --theme-day-card-divider: var(--color-ski-glacier);
      --theme-day-card-shadow: 0 3px 10px rgba(31, 44, 61, 0.08);

      --theme-day-headline-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-headline-weight: 600;
      --theme-day-item-title-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-item-title-weight: 600;
    }

    /* Day card — pure-white snow surface with a faint cool glacier
       gradient at the top edge so the card doesn't read as a flat
       white page. */
    body[data-theme="skiTrip"] .day-group {
      position: relative;
      background:
        linear-gradient(
          to bottom,
          rgba(226, 232, 238, 0.4) 0%,
          rgba(226, 232, 238, 0) 50%
        ),
        #FFFFFF;
      border: 1px solid var(--color-ski-glacier);
      border-radius: 12px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    /* Mountain banner — 56px stripe at the top. Sky color comes from
       the per-day `--ski-accent` inline variable; the SVG overlay
       draws the layered mountain silhouettes + snow caps + flurries
       on top, leaving the sky transparent. Hidden on every theme
       except `skiTrip`. */
    .ski-banner { display: none; }
    body[data-theme="skiTrip"] .ski-banner {
      display: block;
      height: 56px;
      background-color: var(--ski-accent);
      background-image: url(/img/ski-mountains.svg?v=20260501a);
      background-size: 100% 100%;
      background-repeat: no-repeat;
      background-position: center;
    }

    /* Header — left-aligned column: small accent eyebrow with the
       trail-shape badge + weekday on top, big bold date underneath,
       italic dek line ("Santa Monica · 3 runs") below that. */
    body[data-theme="skiTrip"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 14px 18px 14px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-ski-midnight-pine);
      letter-spacing: 0.3px;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    /* Stack the weekday + date inside .day-label as a 2-line block,
       and reveal .day-dek as a third italic line. */
    body[data-theme="skiTrip"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 0;
    }
    body[data-theme="skiTrip"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="skiTrip"] .day-weekday {
      font-size: 0.7rem;
      font-weight: 600;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--ski-accent);
      line-height: 1.4;
    }
    /* Trail-shape "badge" rendered before the weekday — small
       accent shape sized to the eyebrow line. Square / circle /
       diamond keyed off the inline `data-ski-shape` attribute. */
    body[data-theme="skiTrip"] .day-weekday::before {
      content: '';
      display: inline-block;
      width: 9px;
      height: 9px;
      background: var(--ski-accent);
      vertical-align: middle;
      margin-right: 8px;
      transform: translateY(-1px);
    }
    body[data-theme="skiTrip"] .day-group[data-ski-shape="circle"] .day-weekday::before {
      border-radius: 50%;
    }
    body[data-theme="skiTrip"] .day-group[data-ski-shape="diamond"] .day-weekday::before {
      transform: translateY(-1px) rotate(45deg) scale(0.78);
    }
    /* The trailing comma after "FRIDAY," is a hint for the inline
       layout in other themes; in the stacked Ski Trip layout we
       don't want it. Strip via JS isn't worth the extra branching;
       just hide it visually with letter-spacing trickery — the
       weekday text-transform already uppercases, so adding a small
       negative right margin and clipping accomplishes nothing
       reliable. Keeping the comma is fine — it reads as a
       light grace note in iOS as well. */
    body[data-theme="skiTrip"] .day-date {
      font-size: 1.5rem;
      font-weight: 700;
      letter-spacing: 1px;
      text-transform: uppercase;
      color: var(--color-ski-midnight-pine);
      line-height: 1.05;
      margin-top: 2px;
    }
    /* Dek line — italic small text below the date. Hidden by
       default for every other theme; revealed in skiTrip. */
    .day-dek { display: none; }
    body[data-theme="skiTrip"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(31, 44, 61, 0.6);
      margin-top: 4px;
    }
    /* Count noun — themed via CSS so we can swap "items" → "runs"
       on Ski Trip without re-rendering. The count number lives in
       the data-count attribute; an "s" lives in data-plural to
       handle 1 vs N. */
    .day-dek-count::after {
      content: attr(data-count) ' item' attr(data-plural);
    }
    body[data-theme="skiTrip"] .day-dek-count::after {
      content: attr(data-count) ' run' attr(data-plural);
    }
    /* Weather badge — pinned to the top-right of the header in ski
       theme so it doesn't get pulled into the stacked column with
       the weekday/date/dek. */
    body[data-theme="skiTrip"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }

    body[data-theme="skiTrip"] .day-toggle {
      color: rgba(31, 44, 61, 0.5);
    }

    /* Items — trail-shape badge for the type icon, accent times,
       Outfit titles. Hairline + centered snowflake divider between
       rows (visual-essence stand-in for the iOS Snowflake shape). */
    body[data-theme="skiTrip"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="skiTrip"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="skiTrip"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(31, 44, 61, 0.03);
    }
    /* Snowflake divider — thin accent hairline + a centered ❄
       glyph in the day's accent. Like Mediterranean's mosaic
       divider, this needs to be absolute-positioned so it doesn't
       become a flex item inside the card row. */
    body[data-theme="skiTrip"] .itinerary-card + .itinerary-card {
      margin-top: 14px;
    }
    body[data-theme="skiTrip"] .itinerary-card + .itinerary-card::before {
      content: '❄';
      position: absolute;
      top: -10px;
      left: 50%;
      transform: translateX(-50%);
      width: 100px;
      height: 14px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 11px;
      color: var(--ski-accent);
      pointer-events: none;
      background:
        linear-gradient(to right,
          transparent 0%,
          color-mix(in srgb, var(--ski-accent) 35%, transparent) 12%,
          color-mix(in srgb, var(--ski-accent) 35%, transparent) 38%,
          transparent 40%,
          transparent 60%,
          color-mix(in srgb, var(--ski-accent) 35%, transparent) 62%,
          color-mix(in srgb, var(--ski-accent) 35%, transparent) 88%,
          transparent 100%);
      background-size: 100% 1px;
      background-position: center;
      background-repeat: no-repeat;
    }

    body[data-theme="skiTrip"] .item-time {
      color: var(--ski-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.7rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }
    body[data-theme="skiTrip"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.05rem;
      color: var(--color-ski-midnight-pine);
    }

    /* Item type badge — trail-shape outline (square / circle /
       diamond) with accent fill at low opacity + accent stroke +
       accent icon glyph. Uses CSS `clip-path` to carve the
       diamond silhouette without rotating the icon inside. */
    body[data-theme="skiTrip"] .item-icon {
      background: color-mix(in srgb, var(--ski-accent) 18%, transparent) !important;
      border: 1.25px solid var(--ski-accent);
      border-radius: 0;
      width: 28px;
      height: 28px;
    }
    body[data-theme="skiTrip"] .day-group[data-ski-shape="circle"] .item-icon {
      border-radius: 50%;
    }
    body[data-theme="skiTrip"] .day-group[data-ski-shape="diamond"] .item-icon {
      transform: rotate(45deg) scale(0.85);
    }
    body[data-theme="skiTrip"] .day-group[data-ski-shape="diamond"] .item-icon svg {
      transform: rotate(-45deg) scale(1.18);
    }
    body[data-theme="skiTrip"] .item-icon svg {
      color: var(--ski-accent);
      width: 16px;
      height: 16px;
      stroke-width: 2;
    }

    /* Detail section headers. */
    body[data-theme="skiTrip"] .item-detail-section h4 {
      color: var(--ski-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.65rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      border-bottom: 1px solid color-mix(in srgb, var(--ski-accent) 30%, transparent);
      padding-bottom: 3px;
    }

    /* Photos — accent border on each thumb. */
    body[data-theme="skiTrip"] .day-photos {
      padding: 0 18px 16px 18px;
    }
    body[data-theme="skiTrip"] .day-photos .day-photo-thumb {
      border: 2px solid var(--ski-accent);
      border-radius: 4px;
    }

    /* Ski Trip chrome — trail blue across FAB / picker / clock-strip
       / drawer / focus ring. Matches iOS
       `darkClockStripBackground = .skiTrailBlue`. */
    body[data-theme="skiTrip"] .tab-btn:hover { color: var(--color-ski-trail-blue); }
    body[data-theme="skiTrip"] .tab-btn.active {
      color: var(--color-ski-trail-blue);
      border-bottom-color: var(--color-ski-trail-blue);
    }
    body[data-theme="skiTrip"] .view-btn.active {
      background: var(--color-ski-trail-blue);
      color: #fff;
    }
    body[data-theme="skiTrip"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(30, 91, 168, 0.92) 0%, rgba(20, 60, 110, 0.92) 100%);
    }
    body[data-theme="skiTrip"] .chat-fab {
      background: linear-gradient(135deg, var(--color-ski-trail-blue) 0%, #143C6E 100%);
      box-shadow: 0 6px 20px rgba(30, 91, 168, 0.35);
    }
    body[data-theme="skiTrip"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(30, 91, 168, 0.5);
    }
    body[data-theme="skiTrip"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-ski-trail-blue) 0%, #143C6E 100%);
    }
    body[data-theme="skiTrip"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(30, 91, 168, 0.92) 0%, rgba(20, 60, 110, 0.92) 100%);
    }
    body[data-theme="skiTrip"] .clock-strip {
      background: var(--color-ski-trail-blue);
    }
    body[data-theme="skiTrip"] .btn-upload {
      background: linear-gradient(135deg, var(--color-ski-trail-blue) 0%, #143C6E 100%);
    }
    body[data-theme="skiTrip"] .assignee-chip.selected {
      background: var(--color-ski-trail-blue);
      border-color: var(--color-ski-trail-blue);
      color: #fff;
    }
    body[data-theme="skiTrip"] :focus-visible {
      outline-color: var(--color-ski-trail-blue);
    }

    /* ─────────────────────────────────────────────────────────────────
       Beach theme
       ─────────────────────────────────────────────────────────────────
       Photographic sand surface with a translucent cream wash for
       legibility, chunky blue-and-white cabana-stripe banner across
       the top, italic Outfit weekday eyebrow + light Outfit date
       headline + sun glyph in the day's accent, italic dek line
       ("Santa Monica, CA · 3 stops"), pebble-shaped (rounded-square)
       type badges, sine-wave dividers between rows, lowercase italic
       detail-section headers underlined with a small wave.

       Per-day data:
         --beach-accent — one of 4 pastels (ocean teal / sunset peach
                          / pale sky / coral bloom), days_since_epoch
                          % 4
         --beach-sand   — one of 2 sand textures, days_since_epoch
                          % 2 (cycle is coprime with the accent so
                          the (sand, accent) pair walks 4 looks)

       iOS reference: BeachDayCard.swift. */
    body[data-theme="beach"] {
      --theme-day-card-bg: var(--color-beach-towel-cream);
      --theme-day-card-border: var(--color-beach-towel-shadow);
      --theme-day-card-text: var(--color-beach-driftwood);
      --theme-day-card-text-muted: rgba(90, 74, 56, 0.55);
      --theme-day-card-accent: var(--color-beach-ocean-teal);
      --theme-day-card-divider: var(--color-beach-towel-shadow);
      --theme-day-card-shadow: 0 4px 12px rgba(90, 74, 56, 0.15);

      --theme-day-headline-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-headline-weight: 300;
      --theme-day-item-title-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-item-title-weight: 500;
    }

    /* Day card — full-bleed sand image dimmed by a 70% cream wash so
       the texture reads as a quiet background and dark driftwood
       text stays legible. Same approach as iOS sandBackground. */
    body[data-theme="beach"] .day-group {
      position: relative;
      background-image: var(--beach-sand);
      background-size: cover;
      background-position: center;
      background-color: var(--color-beach-towel-cream);
      border-radius: 14px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }
    /* Cream wash on top of the sand. Pointer-events disabled so taps
       still hit the underlying card. z-index 0 places it above the
       day-group's own background but below the children (which are
       lifted to z-index 1 below). */
    body[data-theme="beach"] .day-group::before {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--color-beach-towel-cream);
      opacity: 0.7;
      pointer-events: none;
      z-index: 0;
    }
    body[data-theme="beach"] .beach-banner,
    body[data-theme="beach"] .day-header,
    body[data-theme="beach"] .day-items,
    body[data-theme="beach"] .day-photos {
      position: relative;
      z-index: 1;
    }

    /* Cabana stripe banner — 30px tall, 5 horizontal stripes
       (pale-sky 8 / white 3 / denim 8 / white 3 / pale-sky 8) drawn
       with a single linear-gradient. Hidden on every theme except
       `beach`. */
    .beach-banner { display: none; }
    body[data-theme="beach"] .beach-banner {
      display: block;
      height: 30px;
      background: linear-gradient(
        to bottom,
        var(--color-beach-pale-sky) 0,
        var(--color-beach-pale-sky) 8px,
        #FFFFFF 8px,
        #FFFFFF 11px,
        var(--color-beach-denim-blue) 11px,
        var(--color-beach-denim-blue) 19px,
        #FFFFFF 19px,
        #FFFFFF 22px,
        var(--color-beach-pale-sky) 22px,
        var(--color-beach-pale-sky) 30px
      );
    }

    /* Header — italic accent weekday on top, light Outfit date
       headline with a sun glyph next to it, italic dek beneath.
       Uses the same stacked layout as Ski Trip (.day-label /
       .day-dek wrapper). */
    body[data-theme="beach"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 14px 18px 14px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-beach-driftwood);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="beach"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="beach"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="beach"] .day-weekday {
      font-size: 0.78rem;
      font-weight: 500;
      font-style: italic;
      color: var(--beach-accent);
      line-height: 1.4;
      text-transform: none;
      letter-spacing: 0;
    }
    /* Suppress the comma — Beach uses casual mixed-case weekday
       ("Friday" not "FRIDAY") and skips the inline comma so the
       eyebrow reads as a clean date label above the headline. */
    body[data-theme="beach"] .day-weekday::after {
      content: '';
    }
    body[data-theme="beach"] .day-date {
      font-size: 1.65rem;
      font-weight: 300;
      letter-spacing: 0.5px;
      color: var(--color-beach-driftwood);
      line-height: 1.05;
      margin-top: 2px;
    }
    /* Sun glyph rendered after the date — tilted ☀ in the day's
       accent. Done via ::after on .day-date so it inherits the
       baseline and color. */
    body[data-theme="beach"] .day-date::after {
      content: ' ☀';
      font-size: 0.75em;
      color: var(--beach-accent);
      vertical-align: 0.05em;
      font-weight: 400;
    }
    /* Dek line — italic muted small text below the date. The base
       `.day-dek { display: none }` rule from the Ski Trip block
       still applies; we override here to opt in. */
    body[data-theme="beach"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(90, 74, 56, 0.7);
      margin-top: 4px;
    }
    /* Weather badge pinned top-right (matches the Ski Trip pattern). */
    body[data-theme="beach"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }
    body[data-theme="beach"] .day-toggle {
      color: rgba(90, 74, 56, 0.4);
    }

    /* Items — pebble-shaped badges, italic accent times, Outfit
       medium titles in driftwood. Wave dividers between rows. */
    body[data-theme="beach"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="beach"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="beach"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(90, 74, 56, 0.03);
    }
    /* Wave divider between rows — sine wave SVG used as a mask so
       the day's accent (at low alpha) shows through the stroke.
       Absolutely positioned to escape the flex flow inside the
       card. Width centers it under the row's title column. */
    body[data-theme="beach"] .itinerary-card + .itinerary-card {
      margin-top: 12px;
    }
    body[data-theme="beach"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: -8px;
      left: 50%;
      transform: translateX(-50%);
      width: 200px;
      height: 8px;
      background-color: color-mix(in srgb, var(--beach-accent) 55%, transparent);
      -webkit-mask-image: url(/img/beach-wave.svg);
      mask-image: url(/img/beach-wave.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      pointer-events: none;
    }

    body[data-theme="beach"] .item-time {
      color: var(--beach-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 500;
      font-style: italic;
      font-size: 0.78rem;
      letter-spacing: 0;
      text-transform: lowercase;
    }
    body[data-theme="beach"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.05rem;
      color: var(--color-beach-driftwood);
    }

    /* Pebble-shaped type badge — rounded square (50% radius =
       pill) with the day's accent at low opacity, accent icon
       glyph centered. */
    body[data-theme="beach"] .item-icon {
      background: color-mix(in srgb, var(--beach-accent) 18%, transparent) !important;
      border: none;
      border-radius: 14px;
      width: 28px;
      height: 28px;
    }
    body[data-theme="beach"] .item-icon svg {
      color: var(--beach-accent);
      width: 16px;
      height: 16px;
      stroke-width: 1.8;
    }

    /* Detail section headers — lowercase italic in the day's accent
       with a tiny wave underline (same SVG mask trick as the
       between-row divider). */
    body[data-theme="beach"] .item-detail-section h4 {
      color: var(--beach-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 500;
      font-style: italic;
      font-size: 0.78rem;
      letter-spacing: 0;
      text-transform: lowercase;
      padding-bottom: 4px;
      position: relative;
      border-bottom: none;
    }
    body[data-theme="beach"] .item-detail-section h4::after {
      content: '';
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: 4px;
      background-color: color-mix(in srgb, var(--beach-accent) 40%, transparent);
      -webkit-mask-image: url(/img/beach-wave.svg);
      mask-image: url(/img/beach-wave.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      pointer-events: none;
    }

    /* Photos — soft rounded thumbs, no extra border. */
    body[data-theme="beach"] .day-photos {
      padding: 0 18px 16px 18px;
    }
    body[data-theme="beach"] .day-photos .day-photo-thumb {
      border-radius: 12px;
      overflow: hidden;
    }

    /* Beach chrome — ocean teal across FAB / picker / clock-strip
       / drawer / focus ring. Matches iOS
       `darkClockStripBackground = .beachOceanTeal`. */
    body[data-theme="beach"] .tab-btn:hover { color: var(--color-beach-ocean-teal); }
    body[data-theme="beach"] .tab-btn.active {
      color: var(--color-beach-ocean-teal);
      border-bottom-color: var(--color-beach-ocean-teal);
    }
    body[data-theme="beach"] .view-btn.active {
      background: var(--color-beach-ocean-teal);
      color: #fff;
    }
    body[data-theme="beach"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(91, 168, 156, 0.92) 0%, rgba(60, 120, 110, 0.92) 100%);
    }
    body[data-theme="beach"] .chat-fab {
      background: linear-gradient(135deg, var(--color-beach-ocean-teal) 0%, #3C786E 100%);
      box-shadow: 0 6px 20px rgba(91, 168, 156, 0.35);
    }
    body[data-theme="beach"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(91, 168, 156, 0.5);
    }
    body[data-theme="beach"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-beach-ocean-teal) 0%, #3C786E 100%);
    }
    body[data-theme="beach"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(91, 168, 156, 0.92) 0%, rgba(60, 120, 110, 0.92) 100%);
    }
    body[data-theme="beach"] .clock-strip {
      background: var(--color-beach-ocean-teal);
    }
    body[data-theme="beach"] .btn-upload {
      background: linear-gradient(135deg, var(--color-beach-ocean-teal) 0%, #3C786E 100%);
    }
    body[data-theme="beach"] .assignee-chip.selected {
      background: var(--color-beach-ocean-teal);
      border-color: var(--color-beach-ocean-teal);
      color: #fff;
    }
    body[data-theme="beach"] :focus-visible {
      outline-color: var(--color-beach-ocean-teal);
    }

    /* ─────────────────────────────────────────────────────────────────
       Palm Beach Vibes theme
       ─────────────────────────────────────────────────────────────────
       Lilly-Pulitzer-preppy resort: a warm-white card with a light-green
       garden-lattice watermark, a pastel-pink-and-white scalloped awning
       trimmed in gold, a Playfair date with a flamingo beside it, green
       activity icons, solid gold divider lines, and a LIGHT world-clock
       strip with a gold outline. Per-day accent (--palmbeach-accent)
       rotates Lilly pink / kelly green / citrus / pool aqua.
       Mirrors iOS PalmBeachDayCard.swift. */
    body[data-theme="palmBeach"] {
      --theme-day-card-bg: var(--color-pb-lattice-white);
      --theme-day-card-text: var(--color-pb-club-navy);
      --theme-day-headline-font: 'Playfair Display', serif;
      --theme-day-headline-weight: 600;
      --theme-day-item-title-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-item-title-weight: 500;
    }

    /* Card — warm white with a faint light-green garden-lattice
       (criss-cross of thin diagonal lines). */
    body[data-theme="palmBeach"] .day-group {
      position: relative;
      background-color: var(--color-pb-lattice-white);
      background-image:
        repeating-linear-gradient(45deg,
          color-mix(in srgb, var(--color-pb-kelly-green) 16%, transparent) 0 1px,
          transparent 1px 22px),
        repeating-linear-gradient(-45deg,
          color-mix(in srgb, var(--color-pb-kelly-green) 16%, transparent) 0 1px,
          transparent 1px 22px);
      border-radius: 14px;
      box-shadow: 0 4px 12px rgba(30, 44, 79, 0.12);
      overflow: hidden;
    }

    /* Awning — pastel-pink / white vertical stripes, a gold trim line at
       the bottom, and a scalloped pink valance hanging below it. */
    .palmbeach-awning { display: none; }
    body[data-theme="palmBeach"] .palmbeach-awning {
      display: block;
      height: 24px;
      position: relative;
      background:
        linear-gradient(var(--color-pb-brass), var(--color-pb-brass)) bottom / 100% 2px no-repeat,
        repeating-linear-gradient(to right,
          var(--color-pb-awning-pink) 0, var(--color-pb-awning-pink) calc(100% / 14),
          #FFFFFF calc(100% / 14), #FFFFFF calc(100% / 7));
    }
    body[data-theme="palmBeach"] .palmbeach-awning::after {
      content: '';
      position: absolute;
      left: 0;
      right: 0;
      bottom: -7px;
      height: 7px;
      background: radial-gradient(circle at 7px 0, var(--color-pb-awning-pink) 6px, transparent 6.5px);
      background-size: 14px 7px;
      background-repeat: repeat-x;
      pointer-events: none;
    }

    /* Header — italic accent weekday, Playfair date with a flamingo
       beside it, italic dek beneath. */
    body[data-theme="palmBeach"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 14px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-pb-club-navy);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="palmBeach"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="palmBeach"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="palmBeach"] .day-weekday {
      font-size: 0.78rem;
      font-weight: 500;
      font-style: italic;
      color: var(--palmbeach-accent);
      line-height: 1.4;
      text-transform: none;
      letter-spacing: 0;
    }
    body[data-theme="palmBeach"] .day-weekday::after { content: ''; }
    body[data-theme="palmBeach"] .day-date {
      font-family: 'Playfair Display', serif;
      font-size: 1.6rem;
      font-weight: 600;
      letter-spacing: 0;
      color: var(--color-pb-club-navy);
      line-height: 1.05;
      margin-top: 2px;
    }
    /* Flamingo beside the date — the theme's signature mark. */
    body[data-theme="palmBeach"] .day-date::after {
      content: ' 🦩';
      font-size: 0.7em;
      vertical-align: 0.05em;
    }
    body[data-theme="palmBeach"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(30, 44, 79, 0.7);
      margin-top: 4px;
    }
    body[data-theme="palmBeach"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }
    body[data-theme="palmBeach"] .day-toggle {
      color: rgba(30, 44, 79, 0.4);
    }

    /* Items — brass-rimmed badges with GREEN icons, accent italic times,
       solid gold divider lines between rows. */
    body[data-theme="palmBeach"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="palmBeach"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="palmBeach"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(30, 44, 79, 0.03);
    }
    body[data-theme="palmBeach"] .itinerary-card + .itinerary-card {
      margin-top: 12px;
    }
    body[data-theme="palmBeach"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: -7px;
      left: 0;
      right: 0;
      height: 1px;
      background: color-mix(in srgb, var(--color-pb-brass) 50%, transparent);
      pointer-events: none;
    }
    body[data-theme="palmBeach"] .item-time {
      color: var(--palmbeach-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 500;
      font-style: italic;
      font-size: 0.78rem;
      letter-spacing: 0;
      text-transform: lowercase;
    }
    body[data-theme="palmBeach"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.05rem;
      color: var(--color-pb-club-navy);
    }
    /* Brass-rimmed badge, accent tint, GREEN icon (consistent on every
       day — mirrors the iOS scallopBadge). */
    body[data-theme="palmBeach"] .item-icon {
      background: color-mix(in srgb, var(--palmbeach-accent) 16%, transparent) !important;
      border: 1px solid color-mix(in srgb, var(--color-pb-brass) 55%, transparent);
      border-radius: 9px;
      width: 28px;
      height: 28px;
    }
    body[data-theme="palmBeach"] .item-icon svg {
      color: var(--color-pb-kelly-green);
      width: 16px;
      height: 16px;
      stroke-width: 1.8;
    }
    /* Detail section headers — italic accent with a gold underline. */
    body[data-theme="palmBeach"] .item-detail-section h4 {
      color: var(--palmbeach-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 500;
      font-style: italic;
      font-size: 0.78rem;
      letter-spacing: 0;
      text-transform: lowercase;
      padding-bottom: 4px;
      border-bottom: 1px solid color-mix(in srgb, var(--color-pb-brass) 40%, transparent);
    }
    /* Photos — soft rounded thumbs. */
    body[data-theme="palmBeach"] .day-photos {
      padding: 0 18px 16px 18px;
    }
    body[data-theme="palmBeach"] .day-photos .day-photo-thumb {
      border-radius: 12px;
      overflow: hidden;
    }

    /* Chrome — kelly green across FAB / picker / chat / focus, plus a
       LIGHT world-clock strip (warm white + gold outline, dark text)
       unlike the dark slabs every other theme uses. */
    body[data-theme="palmBeach"] .tab-btn:hover { color: var(--color-pb-kelly-green); }
    body[data-theme="palmBeach"] .tab-btn.active {
      color: var(--color-pb-kelly-green);
      border-bottom-color: var(--color-pb-kelly-green);
    }
    body[data-theme="palmBeach"] .view-btn.active {
      background: var(--color-pb-kelly-green);
      color: #fff;
    }
    body[data-theme="palmBeach"] .fab-add-btn {
      background: linear-gradient(135deg, #2A9461 0%, #1F7A4D 100%);
    }
    body[data-theme="palmBeach"] .chat-fab {
      background: linear-gradient(135deg, var(--color-pb-kelly-green) 0%, #145736 100%);
      box-shadow: 0 6px 20px rgba(31, 122, 77, 0.35);
    }
    body[data-theme="palmBeach"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(31, 122, 77, 0.5);
    }
    body[data-theme="palmBeach"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-pb-kelly-green) 0%, #145736 100%);
    }
    body[data-theme="palmBeach"] .trip-chat-fab {
      background: linear-gradient(135deg, #2A9461 0%, #1F7A4D 100%);
    }
    body[data-theme="palmBeach"] .clock-strip {
      background: var(--color-pb-lattice-white);
      border: 1.5px solid var(--color-pb-brass);
    }
    body[data-theme="palmBeach"] .clock-label { color: rgba(30, 44, 79, 0.5); }
    body[data-theme="palmBeach"] .clock-time { color: var(--color-pb-kelly-green); }
    body[data-theme="palmBeach"] .clock-item.trip-clock .clock-time { color: var(--color-pb-citrus); }
    body[data-theme="palmBeach"] .clock-date { color: rgba(30, 44, 79, 0.45); }
    body[data-theme="palmBeach"] .btn-upload {
      background: linear-gradient(135deg, var(--color-pb-kelly-green) 0%, #145736 100%);
    }
    body[data-theme="palmBeach"] .assignee-chip.selected {
      background: var(--color-pb-kelly-green);
      border-color: var(--color-pb-kelly-green);
      color: #fff;
    }
    body[data-theme="palmBeach"] :focus-visible {
      outline-color: var(--color-pb-kelly-green);
    }

    /* ─────────────────────────────────────────────────────────────────
       Mountain theme
       ─────────────────────────────────────────────────────────────────
       WPA-poster surface — warm cream paper with a faint
       topographic-contour pattern drawn behind everything,
       mountain-peak silhouette banner across the top, Playfair
       Bold UPPERCASE TRACKED date headline reading like vintage
       National Park signage. Triangle (peak) badges on items;
       small peak-silhouette dividers between rows.

       Per-day data:
         --mountain-accent — one of 5 NP-poster colors (forest /
                             sunset / sky / granite / sage),
                             days_since_epoch % 5

       iOS reference: MountainDayCard.swift. */
    body[data-theme="mountain"] {
      --theme-day-card-bg: var(--color-mountain-paper);
      --theme-day-card-border: rgba(45, 36, 27, 0.18);
      --theme-day-card-text: var(--color-mountain-bark);
      --theme-day-card-text-muted: rgba(45, 36, 27, 0.55);
      --theme-day-card-accent: var(--color-mountain-forest);
      --theme-day-card-divider: rgba(45, 36, 27, 0.18);
      --theme-day-card-shadow: 0 3px 10px rgba(45, 36, 27, 0.12);

      --theme-day-headline-font: 'Playfair Display', 'Georgia', serif;
      --theme-day-headline-weight: 700;
      --theme-day-item-title-font: 'Playfair Display', 'Georgia', serif;
      --theme-day-item-title-weight: 600;
    }

    /* Day card — cream poster paper with the topographic-contour
       SVG laid behind everything. The 1.5px dark-bark border at low
       opacity reads as the printed border around a vintage poster.
       overflow:hidden clips both the topo and the peak banner so
       the rounded corners stay tight. */
    body[data-theme="mountain"] .day-group {
      position: relative;
      background:
        url(/img/mountain-topo.svg),
        var(--color-mountain-paper);
      background-size: cover, cover;
      background-position: center, center;
      background-repeat: no-repeat;
      border: 1.5px solid rgba(45, 36, 27, 0.18);
      border-radius: 6px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    /* Peak silhouette banner — 22px stripe at the top. A faint
       accent-tinted base wash sits under a zigzag peak-silhouette
       SVG used as a mask so the day's accent paints through.
       Hidden on every theme except `mountain`. */
    .mountain-banner { display: none; }
    body[data-theme="mountain"] .mountain-banner {
      display: block;
      height: 22px;
      position: relative;
      background: color-mix(in srgb, var(--mountain-accent) 15%, transparent);
    }
    body[data-theme="mountain"] .mountain-banner::after {
      content: '';
      position: absolute;
      inset: 0;
      background-color: var(--mountain-accent);
      -webkit-mask-image: url(/img/mountain-peaks.svg);
      mask-image: url(/img/mountain-peaks.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      pointer-events: none;
    }

    /* Header — uppercase tracked weekday in accent + UPPERCASE
       TRACKED Playfair Bold date in dark bark + italic dek line.
       Same stacked layout as Beach / Ski Trip via .day-label. */
    body[data-theme="mountain"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 14px 18px 14px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-mountain-bark);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="mountain"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="mountain"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="mountain"] .day-weekday {
      font-size: 0.7rem;
      font-weight: 600;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: var(--mountain-accent);
      line-height: 1.4;
    }
    body[data-theme="mountain"] .day-weekday::after {
      content: '';
    }
    body[data-theme="mountain"] .day-date {
      font-family: 'Playfair Display', serif;
      font-size: 1.4rem;
      font-weight: 700;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      color: var(--color-mountain-bark);
      line-height: 1.05;
      margin-top: 2px;
    }
    body[data-theme="mountain"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(45, 36, 27, 0.7);
      margin-top: 4px;
    }
    body[data-theme="mountain"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }
    body[data-theme="mountain"] .day-toggle {
      color: rgba(45, 36, 27, 0.5);
    }

    /* Items — triangle (peak) badge for the type icon, accent
       times, Playfair semibold titles in bark. Peak-silhouette
       dividers between rows. */
    body[data-theme="mountain"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="mountain"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="mountain"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(45, 36, 27, 0.03);
    }
    /* Peak divider — small zigzag silhouette quote of the banner
       drawn between rows. Same SVG mask trick as the banner. */
    body[data-theme="mountain"] .itinerary-card + .itinerary-card {
      margin-top: 12px;
    }
    body[data-theme="mountain"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: -10px;
      left: 50%;
      transform: translateX(-50%);
      width: 140px;
      height: 9px;
      background-color: color-mix(in srgb, var(--mountain-accent) 65%, transparent);
      -webkit-mask-image: url(/img/mountain-peaks.svg);
      mask-image: url(/img/mountain-peaks.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      pointer-events: none;
    }

    body[data-theme="mountain"] .item-time {
      color: var(--mountain-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.7rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }
    body[data-theme="mountain"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.1rem;
      color: var(--color-mountain-bark);
    }

    /* Triangle (peak) badge — equilateral-ish triangle clipped by
       polygon, accent fill at low opacity, accent icon on top.
       Built with two stacked elements: the badge plate (the
       background fill via mask-image) and the icon (centered, no
       clipping). */
    body[data-theme="mountain"] .item-icon {
      background: transparent !important;
      border: none;
      border-radius: 0;
      width: 28px;
      height: 26px;
      position: relative;
    }
    body[data-theme="mountain"] .item-icon::before {
      content: '';
      position: absolute;
      inset: 0;
      background: color-mix(in srgb, var(--mountain-accent) 18%, transparent);
      clip-path: polygon(50% 0, 100% 100%, 0 100%);
      pointer-events: none;
    }
    body[data-theme="mountain"] .item-icon::after {
      content: '';
      position: absolute;
      inset: 0;
      border: none;
      background-color: var(--mountain-accent);
      clip-path: polygon(
        50% 0,
        100% 100%,
        99% 100%,
        50% 1.6%,
        1% 100%,
        0 100%
      );
      pointer-events: none;
    }
    body[data-theme="mountain"] .item-icon svg {
      color: var(--mountain-accent);
      width: 14px;
      height: 14px;
      stroke-width: 2;
      position: relative;
      z-index: 1;
      transform: translateY(3px);
    }

    /* Detail section headers — uppercase tracked in accent + thin
       accent underline. */
    body[data-theme="mountain"] .item-detail-section h4 {
      color: var(--mountain-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.65rem;
      letter-spacing: 2px;
      text-transform: uppercase;
      border-bottom: 1px solid color-mix(in srgb, var(--mountain-accent) 40%, transparent);
      padding-bottom: 3px;
    }

    /* Photos — soft rounded thumbs with a thin bark-tinted frame. */
    body[data-theme="mountain"] .day-photos {
      padding: 0 18px 16px 18px;
    }
    body[data-theme="mountain"] .day-photos .day-photo-thumb {
      border: 1px solid rgba(45, 36, 27, 0.4);
      border-radius: 4px;
      overflow: hidden;
    }

    /* Mountain chrome — forest green across FAB / picker /
       clock-strip / drawer / focus ring. Matches iOS
       `darkClockStripBackground = .mountainForest`. */
    body[data-theme="mountain"] .tab-btn:hover { color: var(--color-mountain-forest); }
    body[data-theme="mountain"] .tab-btn.active {
      color: var(--color-mountain-forest);
      border-bottom-color: var(--color-mountain-forest);
    }
    body[data-theme="mountain"] .view-btn.active {
      background: var(--color-mountain-forest);
      color: #fff;
    }
    body[data-theme="mountain"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(45, 82, 57, 0.92) 0%, rgba(25, 50, 35, 0.92) 100%);
    }
    body[data-theme="mountain"] .chat-fab {
      background: linear-gradient(135deg, var(--color-mountain-forest) 0%, #193223 100%);
      box-shadow: 0 6px 20px rgba(45, 82, 57, 0.35);
    }
    body[data-theme="mountain"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(45, 82, 57, 0.5);
    }
    body[data-theme="mountain"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-mountain-forest) 0%, #193223 100%);
    }
    body[data-theme="mountain"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(45, 82, 57, 0.92) 0%, rgba(25, 50, 35, 0.92) 100%);
    }
    body[data-theme="mountain"] .clock-strip {
      background: var(--color-mountain-forest);
    }
    body[data-theme="mountain"] .btn-upload {
      background: linear-gradient(135deg, var(--color-mountain-forest) 0%, #193223 100%);
    }
    body[data-theme="mountain"] .assignee-chip.selected {
      background: var(--color-mountain-forest);
      border-color: var(--color-mountain-forest);
      color: #fff;
    }
    body[data-theme="mountain"] :focus-visible {
      outline-color: var(--color-mountain-forest);
    }

    /* ─────────────────────────────────────────────────────────────────
       Western theme
       ─────────────────────────────────────────────────────────────────
       Aged ochre parchment with a warm radial highlight, barbed-wire
       banner across the top, Rye slab-serif date headline (the
       classic "wanted poster" face — bundled font), sheriff-star
       (★) glyph next to the weekday eyebrow, star-trail dividers
       between rows, bare-icon item badges (no enclosing shape — the
       sheriff stars elsewhere already carry the western motif).
       Custom dek noun: "N on the trail".

       Per-day data:
         --western-accent — one of 5 desert colors (rust / saddle /
                            sage / ochre / burgundy),
                            days_since_epoch % 5

       iOS reference: WesternDayCard.swift. */
    body[data-theme="western"] {
      --theme-day-card-bg: var(--color-western-parchment);
      --theme-day-card-border: var(--color-western-parchment-edge);
      --theme-day-card-text: var(--color-western-leather);
      --theme-day-card-text-muted: rgba(59, 36, 21, 0.55);
      --theme-day-card-accent: var(--color-western-rust);
      --theme-day-card-divider: rgba(59, 36, 21, 0.18);
      --theme-day-card-shadow: 0 3px 10px rgba(59, 36, 21, 0.15);

      --theme-day-headline-font: 'Rye', 'Playfair Display', serif;
      --theme-day-headline-weight: 400;
      --theme-day-item-title-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-item-title-weight: 600;
    }

    /* Day card — aged ochre parchment with a warm radial highlight
       and a 1.5px parchment-edge border. Rounded 6px corners (tight,
       like a wanted-poster's printed border). */
    body[data-theme="western"] .day-group {
      position: relative;
      background:
        radial-gradient(
          ellipse at top left,
          rgba(198, 139, 51, 0.15),
          rgba(198, 139, 51, 0) 50%
        ),
        var(--color-western-parchment);
      border: 1.5px solid var(--color-western-parchment-edge);
      border-radius: 6px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    /* Barbed-wire banner — 14px stripe at the top (with a small
       margin so it sits inside the parchment border). The day's
       accent paints through the SVG via mask-image. Hidden on
       every theme except `western`. */
    .western-banner { display: none; }
    body[data-theme="western"] .western-banner {
      display: block;
      height: 14px;
      margin: 8px 8px 0 8px;
      background-color: var(--western-accent);
      -webkit-mask-image: url(/img/western-barbed-wire.svg);
      mask-image: url(/img/western-barbed-wire.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
    }

    /* Header — sheriff star + uppercase tracked weekday in accent on
       top, big Rye slab-serif date in accent below, italic dek line
       beneath. Stacked column matches Beach / Ski / Mountain. */
    body[data-theme="western"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 12px 18px 14px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-western-leather);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="western"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="western"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="western"] .day-weekday {
      font-size: 0.7rem;
      font-weight: 600;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--western-accent);
      line-height: 1.4;
    }
    /* Sheriff-star ★ glyph as a ::before on the weekday — Unicode
       black-star at small size in the day's accent. */
    body[data-theme="western"] .day-weekday::before {
      content: '★';
      display: inline-block;
      margin-right: 6px;
      font-size: 0.85em;
      vertical-align: middle;
      transform: translateY(-1px);
    }
    body[data-theme="western"] .day-weekday::after {
      content: '';
    }
    body[data-theme="western"] .day-date {
      font-family: 'Rye', 'Playfair Display', serif;
      font-weight: 400;
      font-size: 1.5rem;
      letter-spacing: 0.5px;
      color: var(--western-accent);
      line-height: 1.05;
      margin-top: 4px;
      text-transform: none;
    }
    body[data-theme="western"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(59, 36, 21, 0.7);
      margin-top: 4px;
    }
    /* Custom dek noun for Western — "N on the trail" instead of
       the default "N items". Singular vs plural reads naturally
       either way ("1 on the trail" / "3 on the trail"). */
    body[data-theme="western"] .day-dek-count::after {
      content: attr(data-count) ' on the trail';
    }
    body[data-theme="western"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }
    body[data-theme="western"] .day-toggle {
      color: rgba(59, 36, 21, 0.55);
    }

    /* Items — bare type-icon glyph (no enclosing shape), accent
       times, Outfit semibold titles in leather. Star-trail
       dividers between rows. */
    body[data-theme="western"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="western"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="western"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(59, 36, 21, 0.03);
    }
    /* Star-trail divider — hairline + 3 small ★ glyphs centered.
       Implemented as ::before pseudo with a centered text content
       (the stars) plus a thin background line under it. */
    body[data-theme="western"] .itinerary-card + .itinerary-card {
      margin-top: 14px;
    }
    body[data-theme="western"] .itinerary-card + .itinerary-card::before {
      content: '★    ★    ★';
      position: absolute;
      top: -10px;
      left: 50%;
      transform: translateX(-50%);
      width: 140px;
      height: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 0.75rem;
      letter-spacing: 0;
      color: color-mix(in srgb, var(--western-accent) 85%, transparent);
      pointer-events: none;
      background: linear-gradient(
        to right,
        transparent 0,
        color-mix(in srgb, var(--western-accent) 40%, transparent) 8%,
        color-mix(in srgb, var(--western-accent) 40%, transparent) 92%,
        transparent 100%
      );
      background-size: 100% 1px;
      background-position: center;
      background-repeat: no-repeat;
    }

    body[data-theme="western"] .item-time {
      color: var(--western-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.7rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }
    body[data-theme="western"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.05rem;
      color: var(--color-western-leather);
    }

    /* Bare-icon item badge — drops the enclosing shape entirely
       (the sheriff stars on dividers + section headers already
       carry the western motif; doubling it on every item badge
       was too busy on iOS too). Just the icon glyph in the
       day's accent. */
    body[data-theme="western"] .item-icon {
      background: transparent !important;
      border: none;
      border-radius: 0;
      width: 28px;
      height: 28px;
    }
    body[data-theme="western"] .item-icon svg {
      color: var(--western-accent);
      width: 20px;
      height: 20px;
      stroke-width: 2;
    }

    /* Detail section headers — sheriff star + uppercase tracked
       label in accent + thin accent underline. */
    body[data-theme="western"] .item-detail-section h4 {
      color: var(--western-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.65rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      border-bottom: 1px solid color-mix(in srgb, var(--western-accent) 40%, transparent);
      padding-bottom: 3px;
    }
    body[data-theme="western"] .item-detail-section h4::before {
      content: '★ ';
      color: var(--western-accent);
    }

    /* Photos — soft rounded thumbs with a thin parchment-edge frame. */
    body[data-theme="western"] .day-photos {
      padding: 0 18px 16px 18px;
    }
    body[data-theme="western"] .day-photos .day-photo-thumb {
      border: 1px solid var(--color-western-parchment-edge);
      border-radius: 4px;
      overflow: hidden;
    }

    /* Western chrome — rust across FAB / picker / clock-strip /
       drawer / focus ring. Matches iOS
       `darkClockStripBackground = .westernRust`. */
    body[data-theme="western"] .tab-btn:hover { color: var(--color-western-rust); }
    body[data-theme="western"] .tab-btn.active {
      color: var(--color-western-rust);
      border-bottom-color: var(--color-western-rust);
    }
    body[data-theme="western"] .view-btn.active {
      background: var(--color-western-rust);
      color: #fff;
    }
    body[data-theme="western"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(181, 72, 42, 0.92) 0%, rgba(125, 50, 28, 0.92) 100%);
    }
    body[data-theme="western"] .chat-fab {
      background: linear-gradient(135deg, var(--color-western-rust) 0%, #7D321C 100%);
      box-shadow: 0 6px 20px rgba(181, 72, 42, 0.35);
    }
    body[data-theme="western"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(181, 72, 42, 0.5);
    }
    body[data-theme="western"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-western-rust) 0%, #7D321C 100%);
    }
    body[data-theme="western"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(181, 72, 42, 0.92) 0%, rgba(125, 50, 28, 0.92) 100%);
    }
    body[data-theme="western"] .clock-strip {
      background: var(--color-western-rust);
    }
    body[data-theme="western"] .btn-upload {
      background: linear-gradient(135deg, var(--color-western-rust) 0%, #7D321C 100%);
    }
    body[data-theme="western"] .assignee-chip.selected {
      background: var(--color-western-rust);
      border-color: var(--color-western-rust);
      color: #fff;
    }
    body[data-theme="western"] :focus-visible {
      outline-color: var(--color-western-rust);
    }

    /* ─────────────────────────────────────────────────────────────────
       OPEN ROAD theme — American highway road trip.
       Sun-bleached map cream surface; asphalt-black banner across the
       top with center-line yellow dashes + a route-shield carrying a
       stable mile-marker number. Per-day accent rotates route-yellow
       / stop-red / coast-blue / desert-tan. Pattern modeled directly
       on the Western theme block above.

       iOS reference: OpenRoadDayCard.swift. */
    body[data-theme="openRoad"] {
      --theme-day-card-bg: var(--color-road-cream);
      --theme-day-card-border: var(--color-road-cream-edge);
      --theme-day-card-text: var(--color-road-asphalt);
      --theme-day-card-text-muted: rgba(42, 42, 40, 0.6);
      --theme-day-card-accent: var(--openroad-accent, #2A2A28);  /* asphalt fallback for non-.day-group chrome — the per-day rotation only sets --openroad-accent on .day-group inline styles, so outside that scope the var is unset and chrome buttons / chat bubbles would render transparent + cause white-on-white. Matches iOS DayCardTheme.openRoad.chromeAccent (.roadAsphalt). */
      --theme-day-card-divider: rgba(42, 42, 40, 0.18);
      --theme-day-card-shadow: 0 3px 10px rgba(42, 42, 40, 0.18);

      --theme-day-headline-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-headline-weight: 700;
      --theme-day-item-title-font: 'Outfit', 'Helvetica Neue', sans-serif;
      --theme-day-item-title-weight: 600;
    }

    body[data-theme="openRoad"] .day-group {
      background: var(--color-road-cream);
      border: 1px solid var(--color-road-cream-edge);
      border-radius: 6px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    .openroad-banner { display: none; }
    body[data-theme="openRoad"] .openroad-banner {
      display: block;
      position: relative;
      height: 28px;
      background:
        repeating-linear-gradient(
          to right,
          var(--color-road-highway-yellow) 0,
          var(--color-road-highway-yellow) 10px,
          transparent 10px,
          transparent 20px
        ) left center / calc(100% - 50px) 3px no-repeat,
        var(--color-road-asphalt);
    }
    body[data-theme="openRoad"] .openroad-shield {
      position: absolute;
      top: 50%;
      right: 8px;
      transform: translateY(-50%);
      width: 30px;
      height: 32px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 0;
      background: var(--color-road-shield);
      clip-path: polygon(
        15% 0,
        85% 0,
        100% 18%,
        100% 55%,
        50% 100%,
        0 55%,
        0 18%
      );
      box-shadow: inset 0 0 0 1.5px var(--color-road-asphalt);
    }
    body[data-theme="openRoad"] .openroad-shield-rte {
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 5px;
      letter-spacing: 0.5px;
      color: var(--color-road-asphalt);
      line-height: 1;
    }
    body[data-theme="openRoad"] .openroad-shield-num {
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 11px;
      color: var(--color-road-asphalt);
      line-height: 1;
    }

    body[data-theme="openRoad"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 12px 18px 14px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-road-asphalt);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="openRoad"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="openRoad"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="openRoad"] .day-weekday {
      font-size: 0.7rem;
      font-weight: 700;
      letter-spacing: 2px;
      text-transform: uppercase;
      color: var(--openroad-accent);
      line-height: 1.4;
    }
    body[data-theme="openRoad"] .day-weekday::after {
      content: '';
    }
    body[data-theme="openRoad"] .day-date {
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 1.5rem;
      letter-spacing: 0.5px;
      color: var(--color-road-asphalt);
      line-height: 1.05;
      margin-top: 4px;
      text-transform: uppercase;
    }
    body[data-theme="openRoad"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(42, 42, 40, 0.7);
      margin-top: 4px;
    }
    body[data-theme="openRoad"] .day-dek-count::after {
      content: attr(data-count) ' stop' attr(data-plural);
    }
    body[data-theme="openRoad"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }
    body[data-theme="openRoad"] .day-toggle {
      color: rgba(42, 42, 40, 0.55);
    }

    body[data-theme="openRoad"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="openRoad"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="openRoad"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(42, 42, 40, 0.03);
    }
    body[data-theme="openRoad"] .itinerary-card + .itinerary-card {
      margin-top: 14px;
    }
    body[data-theme="openRoad"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: -10px;
      left: 0;
      right: 0;
      height: 2.5px;
      background: repeating-linear-gradient(
        to right,
        var(--color-road-highway-yellow) 0,
        var(--color-road-highway-yellow) 10px,
        transparent 10px,
        transparent 20px
      );
      pointer-events: none;
    }
    body[data-theme="openRoad"] .item-time {
      color: var(--openroad-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 0.7rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }
    body[data-theme="openRoad"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.05rem;
      color: var(--color-road-asphalt);
    }

    /* Open Road chrome — asphalt across FAB / picker / clock-strip
       / drawer / focus ring. Matches iOS chromeAccent + clock-strip
       = .roadAsphalt. */
    body[data-theme="openRoad"] .tab-btn:hover { color: var(--color-road-asphalt); }
    body[data-theme="openRoad"] .tab-btn.active {
      color: var(--color-road-asphalt);
      border-bottom-color: var(--color-road-asphalt);
    }
    body[data-theme="openRoad"] .view-btn.active {
      background: var(--color-road-asphalt);
      color: #fff;
    }
    body[data-theme="openRoad"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(42, 42, 40, 0.95) 0%, rgba(20, 20, 18, 0.95) 100%);
    }
    body[data-theme="openRoad"] .chat-fab {
      background: linear-gradient(135deg, var(--color-road-asphalt) 0%, #141412 100%);
      box-shadow: 0 6px 20px rgba(42, 42, 40, 0.35);
    }
    body[data-theme="openRoad"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(42, 42, 40, 0.5);
    }
    body[data-theme="openRoad"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-road-asphalt) 0%, #141412 100%);
    }
    body[data-theme="openRoad"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(42, 42, 40, 0.95) 0%, rgba(20, 20, 18, 0.95) 100%);
    }
    body[data-theme="openRoad"] .clock-strip {
      background: var(--color-road-asphalt);
    }
    body[data-theme="openRoad"] .btn-upload {
      background: linear-gradient(135deg, var(--color-road-asphalt) 0%, #141412 100%);
    }
    body[data-theme="openRoad"] .assignee-chip.selected {
      background: var(--color-road-asphalt);
      border-color: var(--color-road-asphalt);
      color: #fff;
    }
    body[data-theme="openRoad"] :focus-visible {
      outline-color: var(--color-road-asphalt);
    }

    /* Activity icon — shield-shape badge in bone-white with an
       asphalt outline + asphalt-tinted icon. Mirrors iOS
       OpenRoadDayCard.shieldBadge. */
    body[data-theme="openRoad"] .item-icon {
      background: transparent !important;
      border: none;
      border-radius: 0;
      width: 28px;
      height: 30px;
      position: relative;
    }
    body[data-theme="openRoad"] .item-icon::before {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--color-road-shield);
      clip-path: polygon(
        15% 0,
        85% 0,
        100% 18%,
        100% 55%,
        50% 100%,
        0 55%,
        0 18%
      );
      box-shadow: inset 0 0 0 1.5px var(--color-road-asphalt);
      pointer-events: none;
    }
    body[data-theme="openRoad"] .item-icon svg {
      color: var(--color-road-asphalt);
      width: 14px;
      height: 14px;
      stroke-width: 2;
      position: relative;
      z-index: 1;
      transform: translateY(-1px);
    }

    /* ─────────────────────────────────────────────────────────────────
       COTSWOLDS theme — English countryside afternoon.
       Stone-paper card surface with a photographic landscape banner
       running across the top of each card (6 landscape photos
       cycled per-day, 2 with bottom-biased crop). Hedgerow rule
       along the lower edge of the banner. Playfair italic serif
       headline. Per-day accent: hedgerow / rose / moss / thistle.
       Pattern modeled on the Western theme block.

       iOS reference: CotswoldsDayCard.swift. */
    body[data-theme="cotswolds"] {
      --theme-day-card-bg: var(--color-cotswold-stone);
      --theme-day-card-border: var(--color-cotswold-stone-edge);
      --theme-day-card-text: var(--color-cotswold-ink);
      --theme-day-card-text-muted: rgba(61, 53, 42, 0.65);
      --theme-day-card-accent: var(--cotswolds-accent, #3F5C3D);  /* hedgerow fallback for non-.day-group chrome — see openRoad note above. */
      --theme-day-card-divider: rgba(61, 53, 42, 0.18);
      --theme-day-card-shadow: 0 3px 10px rgba(61, 53, 42, 0.12);

      --theme-day-headline-font: 'Playfair Display', serif;
      --theme-day-headline-weight: 400;
      --theme-day-item-title-font: 'Playfair Display', serif;
      --theme-day-item-title-weight: 400;
    }

    body[data-theme="cotswolds"] .day-group {
      position: relative;
      background:
        radial-gradient(
          ellipse at bottom right,
          rgba(184, 148, 86, 0.12),
          rgba(184, 148, 86, 0) 60%
        ),
        var(--color-cotswold-stone);
      border: 1px solid var(--color-cotswold-stone-edge);
      border-radius: 6px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    .cotswolds-banner { display: none; }
    body[data-theme="cotswolds"] .cotswolds-banner {
      display: block;
      position: relative;
      height: 240px;
      background-image: var(--cotswolds-photo);
      background-size: cover;
      background-position: center var(--cotswolds-photo-y);
      background-repeat: no-repeat;
    }
    body[data-theme="cotswolds"] .cotswolds-banner::after {
      content: '';
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: 1.25px;
      background: var(--cotswolds-accent);
      opacity: 0.65;
    }

    body[data-theme="cotswolds"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 12px 18px 14px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-cotswold-ink);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="cotswolds"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="cotswolds"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="cotswolds"] .day-weekday {
      font-size: 0.7rem;
      font-weight: 600;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: var(--cotswolds-accent);
      line-height: 1.4;
    }
    body[data-theme="cotswolds"] .day-weekday::after {
      content: '';
    }
    body[data-theme="cotswolds"] .day-date {
      font-family: 'Playfair Display', serif;
      font-style: italic;
      font-weight: 400;
      font-size: 1.6rem;
      letter-spacing: 0;
      color: var(--color-cotswold-ink);
      line-height: 1.05;
      margin-top: 4px;
      text-transform: none;
    }
    body[data-theme="cotswolds"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(61, 53, 42, 0.7);
      margin-top: 4px;
    }
    body[data-theme="cotswolds"] .day-dek-count::after {
      content: attr(data-count) ' stop' attr(data-plural);
    }
    body[data-theme="cotswolds"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }
    body[data-theme="cotswolds"] .day-toggle {
      color: rgba(61, 53, 42, 0.55);
    }

    body[data-theme="cotswolds"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="cotswolds"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="cotswolds"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(61, 53, 42, 0.03);
    }
    body[data-theme="cotswolds"] .itinerary-card + .itinerary-card {
      margin-top: 14px;
    }
    body[data-theme="cotswolds"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: -7px;
      left: 0;
      right: 0;
      height: 1px;
      background: rgba(61, 53, 42, 0.18);
      pointer-events: none;
    }
    body[data-theme="cotswolds"] .item-time {
      color: var(--cotswolds-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.7rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }
    body[data-theme="cotswolds"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.05rem;
      color: var(--color-cotswold-ink);
    }

    /* Cotswolds chrome — hedgerow green across FAB / picker /
       clock-strip / drawer / focus ring. Matches iOS chromeAccent
       + clock-strip = .cotswoldHedgerow. */
    body[data-theme="cotswolds"] .tab-btn:hover { color: var(--color-cotswold-hedgerow); }
    body[data-theme="cotswolds"] .tab-btn.active {
      color: var(--color-cotswold-hedgerow);
      border-bottom-color: var(--color-cotswold-hedgerow);
    }
    body[data-theme="cotswolds"] .view-btn.active {
      background: var(--color-cotswold-hedgerow);
      color: #fff;
    }
    body[data-theme="cotswolds"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(63, 92, 61, 0.92) 0%, rgba(40, 65, 38, 0.92) 100%);
    }
    body[data-theme="cotswolds"] .chat-fab {
      background: linear-gradient(135deg, var(--color-cotswold-hedgerow) 0%, #284126 100%);
      box-shadow: 0 6px 20px rgba(63, 92, 61, 0.35);
    }
    body[data-theme="cotswolds"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(63, 92, 61, 0.5);
    }
    body[data-theme="cotswolds"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-cotswold-hedgerow) 0%, #284126 100%);
    }
    body[data-theme="cotswolds"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(63, 92, 61, 0.92) 0%, rgba(40, 65, 38, 0.92) 100%);
    }
    body[data-theme="cotswolds"] .clock-strip {
      background: var(--color-cotswold-hedgerow);
    }
    body[data-theme="cotswolds"] .btn-upload {
      background: linear-gradient(135deg, var(--color-cotswold-hedgerow) 0%, #284126 100%);
    }
    body[data-theme="cotswolds"] .assignee-chip.selected {
      background: var(--color-cotswold-hedgerow);
      border-color: var(--color-cotswold-hedgerow);
      color: #fff;
    }
    body[data-theme="cotswolds"] :focus-visible {
      outline-color: var(--color-cotswold-hedgerow);
    }

    /* Activity icon — round botanical-illustration medallion in
       cream stone with an accent ring + accent-tinted icon. Mirrors
       iOS CotswoldsDayCard.roundLeafBadge. */
    body[data-theme="cotswolds"] .item-icon {
      background: transparent !important;
      border: none;
      border-radius: 0;
      width: 28px;
      height: 28px;
      position: relative;
    }
    body[data-theme="cotswolds"] .item-icon::before {
      content: '';
      position: absolute;
      inset: 0;
      background: color-mix(in srgb, var(--cotswolds-accent) 14%, transparent);
      border: 1.25px solid color-mix(in srgb, var(--cotswolds-accent) 70%, transparent);
      border-radius: 50%;
      pointer-events: none;
    }
    body[data-theme="cotswolds"] .item-icon svg {
      color: var(--cotswolds-accent);
      width: 14px;
      height: 14px;
      stroke-width: 2;
      position: relative;
      z-index: 1;
    }

    /* Cotswolds banner — responsive height. The 240px desktop
       value crops too tightly on the sides at narrow viewports.
       Stepping the height down keeps the box landscape-shaped. */
    @media (max-width: 768px) {
      body[data-theme="cotswolds"] .cotswolds-banner {
        height: 180px;
      }
    }
    @media (max-width: 480px) {
      body[data-theme="cotswolds"] .cotswolds-banner {
        height: 140px;
      }
    }

    /* ─────────────────────────────────────────────────────────────────
       CAFÉ AU LAIT theme — Paris bistro chalkboard.
       Striped Parisian awning + chalkboard panel carrying the date
       in chalk-cream Architects Daughter. Cream menu-paper card
       body. Chalk tier (Architects Daughter) for headlines + items;
       printed-tier (Playfair italic) for supporting body copy.
       Per-day accent: bistro-red / brass / cassis / jardin.

       iOS reference: CafeAuLaitDayCard.swift. */
    body[data-theme="cafeAuLait"] {
      --theme-day-card-bg: var(--color-cafe-cream);
      --theme-day-card-border: var(--color-cafe-cream-edge);
      --theme-day-card-text: var(--color-cafe-ink);
      --theme-day-card-text-muted: rgba(42, 31, 24, 0.65);
      --theme-day-card-accent: var(--cafe-accent, #A6353A);  /* bistro-red fallback for non-.day-group chrome — see openRoad note above. */
      --theme-day-card-divider: rgba(42, 31, 24, 0.15);
      --theme-day-card-shadow: 0 3px 10px rgba(42, 31, 24, 0.12);

      --theme-day-headline-font: 'Architects Daughter', cursive;
      --theme-day-headline-weight: 400;
      --theme-day-item-title-font: 'Architects Daughter', cursive;
      --theme-day-item-title-weight: 400;
    }

    body[data-theme="cafeAuLait"] .day-group {
      background: var(--color-cafe-cream);
      border: 1px solid var(--color-cafe-cream-edge);
      border-radius: 6px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    .cafe-awning { display: none; }
    body[data-theme="cafeAuLait"] .cafe-awning {
      display: block;
      height: 8px;
      background: repeating-linear-gradient(
        to right,
        var(--cafe-accent) 0,
        var(--cafe-accent) calc(100% / 14),
        var(--color-cafe-cream) calc(100% / 14),
        var(--color-cafe-cream) calc(100% / 7)
      );
    }

    .cafe-chalkboard,
    .cafe-chalk-weekday,
    .cafe-chalk-date { display: none; }
    body[data-theme="cafeAuLait"] .cafe-chalkboard {
      display: block;
      height: 80px;
      padding: 10px 18px 0 18px;
      background: var(--color-cafe-chalkboard);
      position: relative;
    }
    body[data-theme="cafeAuLait"] .cafe-chalk-weekday {
      display: block;
      font-family: 'Architects Daughter', cursive;
      font-size: 0.78rem;
      letter-spacing: 2px;
      color: rgba(244, 236, 220, 0.78);
      text-transform: uppercase;
      line-height: 1.2;
    }
    body[data-theme="cafeAuLait"] .cafe-chalk-date {
      display: block;
      font-family: 'Architects Daughter', cursive;
      font-size: 1.65rem;
      color: var(--color-cafe-chalk);
      line-height: 1.05;
      margin-top: 4px;
    }

    body[data-theme="cafeAuLait"] .day-weekday,
    body[data-theme="cafeAuLait"] .day-date {
      display: none;
    }

    body[data-theme="cafeAuLait"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 10px 18px 12px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-cafe-ink);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="cafeAuLait"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 2px;
    }
    body[data-theme="cafeAuLait"] .day-header > span:first-child::before {
      content: "TODAY'S MENU";
      display: block;
      font-family: 'Architects Daughter', cursive;
      font-size: 0.78rem;
      letter-spacing: 2px;
      color: var(--cafe-accent);
      text-transform: uppercase;
      line-height: 1.2;
    }
    body[data-theme="cafeAuLait"] .day-dek {
      display: inline-block;
      font-family: 'Playfair Display', serif;
      font-style: italic;
      font-size: 0.78rem;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(42, 31, 24, 0.7);
      margin-top: 2px;
    }
    body[data-theme="cafeAuLait"] .day-dek-count::after {
      content: attr(data-count) ' stop' attr(data-plural);
    }
    body[data-theme="cafeAuLait"] .day-header .day-weather {
      position: absolute;
      top: 10px;
      right: 40px;
    }
    body[data-theme="cafeAuLait"] .day-toggle {
      color: rgba(42, 31, 24, 0.55);
    }

    body[data-theme="cafeAuLait"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="cafeAuLait"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="cafeAuLait"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(42, 31, 24, 0.03);
    }
    body[data-theme="cafeAuLait"] .itinerary-card + .itinerary-card {
      margin-top: 12px;
    }
    body[data-theme="cafeAuLait"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: -6px;
      left: 0;
      right: 0;
      height: 1px;
      background: rgba(42, 31, 24, 0.15);
      pointer-events: none;
    }
    body[data-theme="cafeAuLait"] .item-time {
      color: var(--cafe-accent);
      font-family: 'Architects Daughter', cursive;
      font-size: 0.8rem;
      letter-spacing: 1px;
      text-transform: uppercase;
    }
    body[data-theme="cafeAuLait"] .item-title {
      font-family: 'Architects Daughter', cursive;
      font-weight: 400;
      font-size: 1.15rem;
      color: var(--color-cafe-ink);
    }

    body[data-theme="cafeAuLait"] .tab-btn:hover { color: var(--color-cafe-bistro-red); }
    body[data-theme="cafeAuLait"] .tab-btn.active {
      color: var(--color-cafe-bistro-red);
      border-bottom-color: var(--color-cafe-bistro-red);
    }
    body[data-theme="cafeAuLait"] .view-btn.active {
      background: var(--color-cafe-bistro-red);
      color: #fff;
    }
    body[data-theme="cafeAuLait"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(166, 53, 58, 0.95) 0%, rgba(120, 35, 40, 0.95) 100%);
    }
    body[data-theme="cafeAuLait"] .chat-fab {
      background: linear-gradient(135deg, var(--color-cafe-bistro-red) 0%, #782328 100%);
      box-shadow: 0 6px 20px rgba(166, 53, 58, 0.35);
    }
    body[data-theme="cafeAuLait"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(166, 53, 58, 0.5);
    }
    body[data-theme="cafeAuLait"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-cafe-bistro-red) 0%, #782328 100%);
    }
    body[data-theme="cafeAuLait"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(166, 53, 58, 0.95) 0%, rgba(120, 35, 40, 0.95) 100%);
    }
    body[data-theme="cafeAuLait"] .clock-strip {
      background: var(--color-cafe-chalkboard);
    }
    body[data-theme="cafeAuLait"] .btn-upload {
      background: linear-gradient(135deg, var(--color-cafe-bistro-red) 0%, #782328 100%);
    }
    body[data-theme="cafeAuLait"] .assignee-chip.selected {
      background: var(--color-cafe-bistro-red);
      border-color: var(--color-cafe-bistro-red);
      color: #fff;
    }
    body[data-theme="cafeAuLait"] :focus-visible {
      outline-color: var(--color-cafe-bistro-red);
    }

    body[data-theme="cafeAuLait"] .item-icon {
      background: transparent !important;
      border: none;
      border-radius: 0;
      width: 28px;
      height: 28px;
      position: relative;
    }
    body[data-theme="cafeAuLait"] .item-icon::before {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--color-cafe-cream);
      border: 1.25px solid var(--color-cafe-brass);
      border-radius: 50%;
      box-shadow:
        inset 0 0 0 1px color-mix(in srgb, var(--cafe-accent) 55%, transparent);
      pointer-events: none;
    }
    body[data-theme="cafeAuLait"] .item-icon svg {
      color: var(--cafe-accent);
      width: 14px;
      height: 14px;
      stroke-width: 2;
      position: relative;
      z-index: 1;
    }

    /* ─────────────────────────────────────────────────────────────────
       VINTAGE HAWAII (tropicalJungle) — verdant rainforest interior.
       Sun-cream paper card surface with a per-day photographic
       backdrop muted by a heavy cream wash. Per-day accent: canopy
       / canopy-dark / fern / hibiscus.

       iOS reference: TropicalJungleDayCard.swift. */
    body[data-theme="tropicalJungle"] {
      --theme-day-card-bg: var(--color-tropical-sun-cream);
      --theme-day-card-border: var(--color-tropical-mist-green);
      --theme-day-card-text: var(--color-tropical-bark);
      --theme-day-card-text-muted: rgba(74, 47, 30, 0.65);
      --theme-day-card-accent: var(--tropical-accent, #2F6041);  /* canopy fallback for non-.day-group chrome — see openRoad note above. */
      --theme-day-card-divider: rgba(74, 47, 30, 0.15);
      --theme-day-card-shadow: 0 3px 10px rgba(74, 47, 30, 0.18);

      --theme-day-headline-font: 'Playfair Display', serif;
      --theme-day-headline-weight: 700;
      --theme-day-item-title-font: 'Playfair Display', serif;
      --theme-day-item-title-weight: 600;
    }

    body[data-theme="tropicalJungle"] .day-group {
      position: relative;
      background:
        radial-gradient(
          ellipse at top left,
          rgba(156, 107, 14, 0.18),
          rgba(156, 107, 14, 0) 50%
        ),
        linear-gradient(
          rgba(250, 241, 220, 0.85),
          rgba(250, 241, 220, 0.85)
        ),
        var(--tropical-photo);
      background-size: auto, auto, cover;
      background-position: 0 0, 0 0, center top;
      background-repeat: no-repeat, no-repeat, no-repeat;
      border: 1px solid var(--color-tropical-mist-green);
      border-radius: 6px;
      box-shadow: var(--theme-day-card-shadow);
      overflow: hidden;
    }

    .tropical-banner { display: none; }

    body[data-theme="tropicalJungle"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 14px 18px 12px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-tropical-bark);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="tropicalJungle"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="tropicalJungle"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="tropicalJungle"] .day-weekday {
      font-size: 0.7rem;
      font-weight: 600;
      letter-spacing: 2.5px;
      text-transform: uppercase;
      color: var(--color-tropical-amber);
      line-height: 1.4;
    }
    body[data-theme="tropicalJungle"] .day-weekday::after {
      content: '';
    }
    body[data-theme="tropicalJungle"] .day-date {
      font-family: 'Playfair Display', serif;
      font-weight: 700;
      font-size: 1.5rem;
      letter-spacing: 0.5px;
      color: var(--color-tropical-bark);
      line-height: 1.05;
      margin-top: 4px;
      text-transform: none;
    }
    body[data-theme="tropicalJungle"] .day-dek {
      display: inline-block;
      font-size: 0.78rem;
      font-style: italic;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: rgba(74, 47, 30, 0.7);
      margin-top: 4px;
    }
    body[data-theme="tropicalJungle"] .day-dek-count::after {
      content: attr(data-count) ' stop' attr(data-plural);
    }
    body[data-theme="tropicalJungle"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
    }
    body[data-theme="tropicalJungle"] .day-toggle {
      color: rgba(74, 47, 30, 0.55);
    }

    body[data-theme="tropicalJungle"] .day-items {
      padding: 4px 18px 16px 18px;
    }
    body[data-theme="tropicalJungle"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 10px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="tropicalJungle"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(74, 47, 30, 0.03);
    }
    body[data-theme="tropicalJungle"] .itinerary-card + .itinerary-card {
      margin-top: 14px;
    }
    body[data-theme="tropicalJungle"] .itinerary-card + .itinerary-card::before {
      content: '🌿';
      position: absolute;
      top: -10px;
      left: 50%;
      transform: translateX(-50%);
      font-size: 14px;
      letter-spacing: 4px;
      color: var(--tropical-accent);
      opacity: 0.5;
      pointer-events: none;
    }

    body[data-theme="tropicalJungle"] .item-time {
      color: var(--tropical-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 600;
      font-size: 0.7rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
    }
    body[data-theme="tropicalJungle"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.05rem;
      color: var(--color-tropical-bark);
    }

    body[data-theme="tropicalJungle"] .tab-btn:hover { color: var(--color-tropical-canopy); }
    body[data-theme="tropicalJungle"] .tab-btn.active {
      color: var(--color-tropical-canopy);
      border-bottom-color: var(--color-tropical-canopy);
    }
    body[data-theme="tropicalJungle"] .view-btn.active {
      background: var(--color-tropical-canopy);
      color: #fff;
    }
    body[data-theme="tropicalJungle"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(47, 96, 65, 0.95) 0%, rgba(27, 58, 36, 0.95) 100%);
    }
    body[data-theme="tropicalJungle"] .chat-fab {
      background: linear-gradient(135deg, var(--color-tropical-canopy) 0%, var(--color-tropical-canopy-dark) 100%);
      box-shadow: 0 6px 20px rgba(47, 96, 65, 0.35);
    }
    body[data-theme="tropicalJungle"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(47, 96, 65, 0.5);
    }
    body[data-theme="tropicalJungle"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-tropical-canopy) 0%, var(--color-tropical-canopy-dark) 100%);
    }
    body[data-theme="tropicalJungle"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(47, 96, 65, 0.95) 0%, rgba(27, 58, 36, 0.95) 100%);
    }
    body[data-theme="tropicalJungle"] .clock-strip {
      background: var(--color-tropical-canopy-dark);
    }
    body[data-theme="tropicalJungle"] .btn-upload {
      background: linear-gradient(135deg, var(--color-tropical-canopy) 0%, var(--color-tropical-canopy-dark) 100%);
    }
    body[data-theme="tropicalJungle"] .assignee-chip.selected {
      background: var(--color-tropical-canopy);
      border-color: var(--color-tropical-canopy);
      color: #fff;
    }
    body[data-theme="tropicalJungle"] :focus-visible {
      outline-color: var(--color-tropical-canopy);
    }

    body[data-theme="tropicalJungle"] .item-icon {
      background: transparent !important;
      border: none;
      border-radius: 0;
      width: 28px;
      height: 30px;
      position: relative;
    }
    body[data-theme="tropicalJungle"] .item-icon::before {
      content: '';
      position: absolute;
      inset: 0;
      background: color-mix(in srgb, var(--tropical-accent) 18%, transparent);
      clip-path: polygon(
        50% 0%,
        85% 18%, 100% 50%,
        85% 78%, 50% 100%,
        15% 78%, 0% 50%,
        15% 18%
      );
      pointer-events: none;
    }
    body[data-theme="tropicalJungle"] .item-icon::after {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--tropical-accent);
      clip-path: polygon(
        50% 0%,
        85% 18%, 100% 50%,
        85% 78%, 50% 100%,
        15% 78%, 0% 50%,
        15% 18%,
        50% 0%,
        49% 1.6%,
        16% 19%, 1% 50%,
        16% 78%, 50% 99%,
        85% 78%, 99% 50%,
        85% 19%
      );
      pointer-events: none;
    }
    body[data-theme="tropicalJungle"] .item-icon svg {
      color: var(--tropical-accent);
      width: 14px;
      height: 14px;
      stroke-width: 2;
      position: relative;
      z-index: 1;
    }

    /* ─────────────────────────────────────────────────────────────────
       TOKYO NIGHTS theme — late-night metropolis, structurally
       inverted (dark navy + neon glow). City-skyline silhouette
       at the bottom of each card with lit-window dot glints, scan-
       line CRT overlay, multi-shadow neon-glow headline.

       iOS reference: TokyoNightsDayCard.swift. */
    body[data-theme="tokyoNights"] {
      --theme-day-card-bg: var(--color-tokyo-night);
      --theme-day-card-border: rgba(124, 140, 160, 0.22);
      --theme-day-card-text: var(--color-tokyo-bone);
      --theme-day-card-text-muted: var(--color-tokyo-mist);
      --theme-day-card-accent: var(--tokyo-accent, #FF2D87);  /* magenta fallback for non-.day-group chrome — see openRoad note above. */
      --theme-day-card-divider: rgba(124, 140, 160, 0.2);
      --theme-day-card-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);

      --theme-day-headline-font: 'Outfit', sans-serif;
      --theme-day-headline-weight: 800;
      --theme-day-item-title-font: 'Outfit', sans-serif;
      --theme-day-item-title-weight: 600;
    }

    body[data-theme="tokyoNights"] .day-group {
      position: relative;
      background:
        repeating-linear-gradient(
          to bottom,
          rgba(255, 255, 255, 0.04) 0,
          rgba(255, 255, 255, 0.04) 0.5px,
          transparent 0.5px,
          transparent 3px
        ),
        linear-gradient(
          to bottom,
          var(--color-tokyo-asphalt) 0%,
          var(--color-tokyo-night) 50%,
          var(--color-tokyo-onyx) 100%
        );
      border: 1px solid rgba(124, 140, 160, 0.22);
      border-radius: 8px;
      box-shadow:
        var(--theme-day-card-shadow),
        0 0 14px color-mix(in srgb, var(--tokyo-accent) 50%, transparent);
      overflow: hidden;
      color: var(--color-tokyo-bone);
    }

    /* Skyline rendered as `.day-items::after` below. */

    body[data-theme="tokyoNights"] .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 14px 18px 16px 18px;
      font-family: 'Outfit', sans-serif;
      color: var(--color-tokyo-bone);
      letter-spacing: 0;
      text-transform: none;
      position: relative;
      align-items: flex-start;
    }
    body[data-theme="tokyoNights"] .day-header > span:first-child {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="tokyoNights"] .day-label {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }
    body[data-theme="tokyoNights"] .day-weekday {
      font-size: 0.7rem;
      font-weight: 600;
      letter-spacing: 3px;
      text-transform: uppercase;
      color: var(--tokyo-accent);
      line-height: 1.4;
    }
    body[data-theme="tokyoNights"] .day-weekday::after {
      content: '';
    }
    body[data-theme="tokyoNights"] .day-date {
      font-family: 'Outfit', sans-serif;
      font-weight: 800;
      font-size: 1.55rem;
      letter-spacing: 2.5px;
      color: var(--color-tokyo-bone);
      line-height: 1.05;
      margin-top: 6px;
      text-transform: uppercase;
      text-shadow:
        0 0 1px var(--tokyo-accent),
        0 0 4px var(--tokyo-accent),
        0 0 10px color-mix(in srgb, var(--tokyo-accent) 60%, transparent),
        0 0 18px color-mix(in srgb, var(--tokyo-accent) 35%, transparent);
    }
    body[data-theme="tokyoNights"] .day-dek {
      display: inline-block;
      font-family: 'Outfit', sans-serif;
      font-size: 0.78rem;
      font-weight: 400;
      letter-spacing: 0;
      text-transform: none;
      color: var(--color-tokyo-mist);
      margin-top: 4px;
    }
    body[data-theme="tokyoNights"] .day-dek-count::after {
      content: attr(data-count) ' stop' attr(data-plural);
    }
    body[data-theme="tokyoNights"] .day-header .day-weather {
      position: absolute;
      top: 14px;
      right: 40px;
      color: var(--color-tokyo-cyan);
    }
    body[data-theme="tokyoNights"] .day-toggle {
      color: var(--color-tokyo-mist);
    }

    /* Neon accent rule under the day header. Mirrors iOS
       neonAccentLine. */
    body[data-theme="tokyoNights"] .day-header::after {
      content: '';
      position: absolute;
      left: 18px;
      right: 18px;
      bottom: 0;
      height: 1.5px;
      background: var(--tokyo-accent);
      box-shadow:
        0 0 2px var(--tokyo-accent),
        0 0 6px color-mix(in srgb, var(--tokyo-accent) 60%, transparent),
        0 0 12px color-mix(in srgb, var(--tokyo-accent) 30%, transparent);
      pointer-events: none;
    }

    body[data-theme="tokyoNights"] .day-items {
      padding: 4px 18px 0 18px;
      position: relative;
    }
    body[data-theme="tokyoNights"] .itinerary-card {
      background: transparent;
      border: none;
      box-shadow: none;
      border-radius: 0;
      padding: 12px 0;
      margin-bottom: 0;
      position: relative;
    }
    body[data-theme="tokyoNights"] .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(124, 140, 160, 0.05);
    }
    body[data-theme="tokyoNights"] .itinerary-card + .itinerary-card::before {
      content: '';
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      height: 1px;
      background: color-mix(in srgb, var(--tokyo-accent) 30%, transparent);
      box-shadow: 0 0 4px color-mix(in srgb, var(--tokyo-accent) 25%, transparent);
      pointer-events: none;
    }
    /* Skyline — dedicated `.tokyo-skyline-band` element emitted
       between the last activity and the photos. Hidden on all
       other themes. */
    .tokyo-skyline-band { display: none; }
    body[data-theme="tokyoNights"] .tokyo-skyline-band {
      display: block;
      margin: 18px -18px 0 -18px;
      height: 60px;
      background: var(--tokyo-accent);
      -webkit-mask-image: url(/img/tokyo-skyline.svg);
      mask-image: url(/img/tokyo-skyline.svg);
      -webkit-mask-size: 100% 100%;
      mask-size: 100% 100%;
      -webkit-mask-repeat: no-repeat;
      mask-repeat: no-repeat;
      pointer-events: none;
      filter:
        drop-shadow(0 0 3px var(--tokyo-accent))
        drop-shadow(0 0 8px color-mix(in srgb, var(--tokyo-accent) 60%, transparent));
    }
    body[data-theme="tokyoNights"] .item-time {
      color: var(--tokyo-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 0.7rem;
      letter-spacing: 2px;
      text-transform: uppercase;
      text-shadow: 0 0 4px color-mix(in srgb, var(--tokyo-accent) 50%, transparent);
    }
    body[data-theme="tokyoNights"] .item-title {
      font-family: var(--theme-day-item-title-font);
      font-weight: var(--theme-day-item-title-weight);
      font-size: 1.02rem;
      color: var(--color-tokyo-bone);
    }

    body[data-theme="tokyoNights"] .tab-btn:hover { color: var(--color-tokyo-magenta); }
    body[data-theme="tokyoNights"] .tab-btn.active {
      color: var(--color-tokyo-magenta);
      border-bottom-color: var(--color-tokyo-magenta);
    }
    body[data-theme="tokyoNights"] .view-btn.active {
      background: var(--color-tokyo-magenta);
      color: #fff;
    }
    body[data-theme="tokyoNights"] .fab-add-btn {
      background: linear-gradient(135deg, rgba(255, 45, 135, 0.95) 0%, rgba(180, 30, 95, 0.95) 100%);
      box-shadow: 0 6px 20px rgba(255, 45, 135, 0.4);
    }
    body[data-theme="tokyoNights"] .chat-fab {
      background: linear-gradient(135deg, var(--color-tokyo-magenta) 0%, #B41E5F 100%);
      box-shadow: 0 6px 20px rgba(255, 45, 135, 0.45);
    }
    body[data-theme="tokyoNights"] .chat-fab:hover {
      box-shadow: 0 8px 28px rgba(255, 45, 135, 0.6);
    }
    body[data-theme="tokyoNights"] .chat-drawer-header {
      background: linear-gradient(135deg, var(--color-tokyo-magenta) 0%, #B41E5F 100%);
    }
    body[data-theme="tokyoNights"] .trip-chat-fab {
      background: linear-gradient(135deg, rgba(255, 45, 135, 0.95) 0%, rgba(180, 30, 95, 0.95) 100%);
    }
    body[data-theme="tokyoNights"] .clock-strip {
      background: var(--color-tokyo-onyx);
    }
    body[data-theme="tokyoNights"] .btn-upload {
      background: linear-gradient(135deg, var(--color-tokyo-magenta) 0%, #B41E5F 100%);
    }
    body[data-theme="tokyoNights"] .assignee-chip.selected {
      background: var(--color-tokyo-magenta);
      border-color: var(--color-tokyo-magenta);
      color: #fff;
    }
    body[data-theme="tokyoNights"] :focus-visible {
      outline-color: var(--color-tokyo-magenta);
    }

    /* Photos — neon-outlined thumbnails in day's accent. */
    body[data-theme="tokyoNights"] .day-photos {
      padding: 12px 18px 18px 18px;
      background: transparent;
    }
    body[data-theme="tokyoNights"] .day-photo-thumb {
      border: 1px solid var(--tokyo-accent);
      border-radius: 4px;
      overflow: hidden;
      box-shadow:
        0 0 4px color-mix(in srgb, var(--tokyo-accent) 60%, transparent),
        0 0 10px color-mix(in srgb, var(--tokyo-accent) 30%, transparent);
      transition: box-shadow 0.2s;
    }
    body[data-theme="tokyoNights"] .day-photo-thumb:hover {
      box-shadow:
        0 0 6px var(--tokyo-accent),
        0 0 14px color-mix(in srgb, var(--tokyo-accent) 50%, transparent);
    }

    body[data-theme="tokyoNights"] .item-icon {
      background: var(--color-tokyo-night) !important;
      border: 1px solid var(--tokyo-accent);
      border-radius: 6px;
      width: 30px;
      height: 30px;
      box-shadow: 0 0 6px color-mix(in srgb, var(--tokyo-accent) 50%, transparent);
      position: relative;
    }
    body[data-theme="tokyoNights"] .item-icon svg {
      color: var(--tokyo-accent);
      width: 16px;
      height: 16px;
      stroke-width: 2;
      filter: drop-shadow(0 0 2px color-mix(in srgb, var(--tokyo-accent) 60%, transparent));
    }

    /* Expanded detail content — section labels in day's accent,
       location link in accent, body text in bone-cream. */
    body[data-theme="tokyoNights"] .item-detail-section h4 {
      color: var(--tokyo-accent);
      font-family: 'Outfit', sans-serif;
      font-weight: 700;
      font-size: 0.65rem;
      letter-spacing: 1.5px;
      text-transform: uppercase;
      border-bottom: 1px solid color-mix(in srgb, var(--tokyo-accent) 40%, transparent);
      padding-bottom: 4px;
      margin-bottom: 6px;
    }
    body[data-theme="tokyoNights"] .item-detail-section p,
    body[data-theme="tokyoNights"] .item-detail-section a {
      color: var(--color-tokyo-bone);
    }
    body[data-theme="tokyoNights"] .item-detail-section a.map-link {
      color: var(--tokyo-accent);
      text-decoration: underline;
    }
    body[data-theme="tokyoNights"] .item-detail-notes {
      color: rgba(232, 234, 240, 0.85);
    }
    body[data-theme="tokyoNights"] .item-doc-link {
      color: var(--color-tokyo-bone);
    }
    body[data-theme="tokyoNights"] .item-doc-link:hover {
      color: var(--tokyo-accent);
    }

    /* ── Modern (Kintinery Default) unified day-card ──
       Mirrors the body:not([data-theme]) overrides in trip.css
       so shared trips with no sharedTheme set render the same
       single-card layout the editor uses. */
    body:not([data-theme]) .day-group {
      background: var(--color-ivory);
      border: 1px solid var(--color-border-light);
      border-radius: 12px;
      box-shadow: 0 2px 8px rgba(10, 31, 20, 0.06);
      overflow: hidden;
    }
    body:not([data-theme]) .day-header {
      background: transparent;
      border: none;
      border-radius: 0;
      padding: 12px 16px;
    }
    body:not([data-theme]) .day-items {
      padding-top: 0;
      padding-bottom: 4px;
    }
    body:not([data-theme]) .day-items.open {
      border-top: 1px solid var(--color-border-light);
    }
    body:not([data-theme]) .itinerary-card {
      background: transparent;
      border: none;
      border-radius: 0;
      box-shadow: none;
      padding: 12px 16px;
      margin: 0;
      border-bottom: 1px solid var(--color-border-light);
    }
    body:not([data-theme]) .day-items > .itinerary-card:last-child {
      border-bottom: none;
    }
    body:not([data-theme]) .itinerary-card:hover {
      transform: none;
      box-shadow: none;
      background: rgba(26, 77, 46, 0.03);
    }
    /* Day photos (when present) sit inside the same card under a
       hairline divider, matching the row spacing. */
    body:not([data-theme]) .day-photos {
      padding: 8px 16px 12px 16px;
      border-top: 1px solid var(--color-border-light);
    }

    /* ── Default day-label rendering — weekday and date inline as
       one phrase. The comma was stripped from the weekday part in
       JS so themes that stack them (Ski Trip / Beach / Mountain /
       Western / Postcard) don't render with a stray comma; we
       inject it back here so the default inline read stays
       "Friday, April 10". Themes that opt into the stacked layout
       suppress this ::after via their own body[data-theme="…"]
       rule (see each theme block above). */
    .day-weekday::after { content: ','; }
    .day-label { display: inline; }
    body[data-theme="skiTrip"] .day-weekday::after { content: ''; }
    /* When any theme is active, suppress the legacy `.day-count`
       pill — themed views surface the count via `.day-dek-count`'s
       theme-aware noun (e.g. "1 item" → "1 run" on Ski Trip). */
    body[data-theme] .day-count { display: none; }
