/* ════════════════════════════════════════════════════════════════════════
   TOMODATCHI SHOP — core styles
   Ported from the main tomodatchi.net character-directory design system.
   ════════════════════════════════════════════════════════════════════════ */

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

:root {
  --bg: #ffffff;
  --grid: rgba(148,179,215,0.18);
  --ink: #2e37fb;
  --muted: #9099ac;
  --border: #c8d8ec;
  --border-soft: #e8f0f9;
  --card-border: 4px;
  --card-border-outer: 8px;
  --radius: 24px;
  --nav-h: 72px;
  --logo-blue: #2e37fb;

  --card-art-height: 200px;
  --card-img-maxheight: 160px;
  --card-img-hover-scale: 1.14;

  /* Site palette — pale grey-blue replaces the 5-colour card system */
  --card-bg: #eaf4fd;
  --card-shade: #d4e8f5;

  /* 5-colour palette kept for reference/other uses */
  --c-pink:   #ffa1bc; --c-pink-shade:   #dc86b9;
  --c-amber:  #ffd39e; --c-amber-shade:  #edbe9f;
  --c-green:  #affcbd; --c-green-shade:  #91cfbd;
  --c-blue:   #9cd8f7; --c-blue-shade:   #8dc1f0;
  --c-purple: #c3a6ff; --c-purple-shade: #9f88f5;
}

/* ─── DARK MODE ───
   Same variable set as :root, redefined. Because every rule in this
   file (and woocommerce.css) already paints through var(--bg),
   var(--ink), var(--logo-blue) etc. instead of hardcoded colours,
   redefining the variables here repaints the vast majority of the
   site automatically — no need to duplicate every selector.

   Two colour moves, per spec:
   1. White surfaces -> a dark grey-blue, weighted toward grey with a
      touch of purple (not a flat near-black, and not a saturated navy).
   2. The mid "ink" blue (buttons, links, headings, borders) -> the
      pale grey-blue already used site-wide for card backgrounds
      (var(--c-blue) / var(--card-bg) family) — so dark mode keeps
      using an existing site colour rather than inventing a new one.

   A small number of hardcoded #fff / var(--logo-blue) spots that
   don't go through these variables are handled with explicit
   [data-theme="dark"] overrides further down this file and in
   woocommerce.css. */
[data-theme="dark"] {
  --bg: #23232e;
  --grid: rgba(156,216,247,0.07);
  --ink: #9cd8f7;
  --muted: #8b93a8;
  --border: #3c3c4d;
  --border-soft: #2d2d3a;
  --logo-blue: #9cd8f7;

  --card-bg: #2a2a38;
  --card-shade: #33333f;
}

html {
  scroll-behavior: smooth;
  /* Safety net: stops any single element that slightly exceeds 100vw
     (the animating search input, the fixed-position nav bar, etc) from
     stretching the page's real horizontal scroll width. overflow-x:
     hidden alone is enough for this — width:100% was removed because
     forcing <html>/<body> to the full viewport width (rather than the
     natural auto width, which already settles at viewport minus the
     scrollbar gutter) was pushing the page's right edge half a
     scrollbar-width too far right, which showed up as a faint grey
     strip under the topbar on the right side. */
  overflow-x: hidden;
}

body.tomo-theme {
  font-family: 'Nunito', sans-serif;
  background-color: var(--bg);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 56px 56px;
  color: var(--ink);
  min-height: 100vh;
  margin: 0;
  padding-top: var(--nav-h);
  /* Same safety net as html above — see note there for why width:100%
     was removed. */
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; }
a { color: inherit; }
ul { list-style: none; margin: 0; padding: 0; }

.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px; overflow: hidden;
  clip: rect(1px,1px,1px,1px);
}

/* ─── NAV ───
   The bar's background/blur/border live on ::before instead of directly
   on .tomo-nav, as a separate paint layer with its own z-index. This is
   what lets the logo's grey outline (z-index 0) sit BEHIND this layer
   while the white outline + logo artwork (z-index 2) sit IN FRONT of it —
   true layered-paper depth, not just a visual approximation. */
.tomo-nav {
  position: fixed; top: 0; left: 0; width: 100%; z-index: 9999;
  display: grid;
  /* Logo column is fixed width, center grows, right is fixed */
  grid-template-columns: auto 1fr auto;
  align-items: center;
  padding: 0 24px;
  height: var(--nav-h);
  gap: 16px;
  overflow: visible;
}

.tomo-nav::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: var(--nav-h);
  background: rgba(255,255,255,0.93);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  /* Was 2px literal, displaying at ~4px on the actual device (2x
     ratio). Doubled to 4px literal to land on the requested 8px
     displayed — then halved to 2px literal per a later request — then
     increased 30% from that (2px -> 2.6px) per a further request. */
  border-bottom: 2.6px solid var(--border);
  z-index: 1;
  pointer-events: none;
}

.tomo-nav-left {
  display: flex; align-items: flex-end; min-width: 0;
  align-self: end;
  /* Never shrink — logo always full size */
  flex-shrink: 0;
  /* Deliberately NOT position:relative / z-index here — that would trap
     .tomo-logo-wrap (and its ::before grey-ring pseudo, and the
     .custom-logo-link white-ring/art layer) in its own stacking
     context and break the layering against .tomo-nav::before (the bar
     background). Those z-indexes need to compare directly against the
     bar's z-index, not against a sub-context rooted here. */
}

.tomo-nav-center {
  display: flex; align-items: center; justify-content: center;
  /* Pinned to the visible nav-h band (not row-height centering) — the
     logo's 115px content box (35px margin-top + 80px height) is taller
     than --nav-h and was stretching the grid row itself, which dragged
     align-self:center siblings down below the painted 72px bar at full
     width. height+align-self:start locks this to the real bar height
     regardless of how tall the logo's box grows. Mobile/wrapped layout
     (max-width:780px) overrides grid-row placement separately below and
     is unaffected. */
  height: var(--nav-h);
  align-self: start;
  /* Allow links to scroll horizontally rather than squash */
  min-width: 0;
  overflow: hidden;
  position: relative;
  z-index: 2;
}

.tomo-nav-right {
  display: flex; align-items: center; justify-content: flex-end;
  gap: 12px; min-width: 0;
  /* Same fix as .tomo-nav-center above — pin to the real bar height
     instead of row-height centering, so search/cart stay vertically
     centered in the visible 72px bar instead of the taller implicit
     grid row caused by the logo's overflow. */
  height: var(--nav-h);
  align-self: start;
  flex-shrink: 0;
  position: relative;
  z-index: 2;
}

.tomo-nav-links {
  display: flex; gap: 2px;
  /* Scroll horizontally when space is tight — no visible scrollbar */
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  flex-wrap: nowrap;
  /* Don't let links shrink or wrap — scroll instead */
  white-space: nowrap;
}
.tomo-nav-links::-webkit-scrollbar { display: none; }

.tomo-nav-mobile-links { display: none; }

/* When the viewport is narrow enough that links genuinely can't show
   (below ~780px), drop them into a second row below the bar */
@media (max-width: 780px) {
  .tomo-nav {
    padding: 0 16px;
    /* Two rows: top row (logo + burger) + lower row (links + search/cart).
       Row 1 is "auto" (not a hard var(--nav-h)) so it sizes to fit the
       logo exactly like desktop's implicit single row does — a fixed
       72px track would clip the logo's natural overflow above the bar
       and push it upward off-screen. The *visual* 72px bar height still
       comes from .tomo-nav::before below; this is just the grid track. */
    /* Column 1 (logo) uses minmax(0, auto) instead of bare auto — a
       bare auto grid track has the same "won't shrink below content's
       natural width" floor that caused the carousel urlbar bug fixed
       earlier in this project. Without the minmax(0, ...) floor here,
       this column refused to shrink below the logo's full natural
       width no matter what flex-shrink/max-width rules were set on
       the logo itself, since those only affect flex layout — they
       have no power over a CSS Grid track's own sizing algorithm.
       This is why the logo kept cropping even after last round's
       max-width:calc() fix was already in place. */
    grid-template-columns: minmax(0, auto) 1fr auto;
    grid-template-rows: auto auto;
    height: auto;
    /* position: fixed is inherited from the base rule above — fixed
       already establishes a positioning context for the ::before/::after
       panels below, so this must NOT be overridden to relative/static
       or the whole bar stops staying pinned on scroll. */
  }
  .tomo-nav-center {
    /* Links take the flexible left portion of the second row */
    grid-column: 1 / 3;
    grid-row: 2;
    justify-content: flex-start;
    overflow-x: auto;
    padding: 8px 0 10px 0;
    min-width: 0;
    /* Undo the desktop-only height:var(--nav-h)/align-self:start pin
       above — row 2 here is a natural auto-height row and must stay
       exactly as it was (this is the layout you said is already
       perfect and must not change). */
    height: auto;
    align-self: auto;
  }
  .tomo-nav-left  {
    grid-column: 1;
    grid-row: 1;
    /* Row 1 is auto-sized to fit the logo (see note on .tomo-nav above),
       same as desktop's implicit row — so the logo sits at the exact
       same vertical position in both states and never jumps. */
    align-self: end;
  }
  .tomo-nav-right {
    /* Search + cart move down into the second row, right-aligned
       next to the links */
    grid-column: 3;
    grid-row: 2;
    flex-shrink: 0;
    padding: 8px 0 10px;
    /* Same revert as .tomo-nav-center above — keep wrapped layout
       untouched. */
    height: auto;
    align-self: auto;
  }
  /* Logo: scale to fit the available width on mobile instead of
     clipping. Desktop's flex-shrink:0 / max-width:none "never squash"
     rules are deliberately left untouched (that's still correct for
     desktop) — this ONLY applies inside the 780px breakpoint, and only
     loosens the hard "never shrink" constraint, it doesn't force a
     smaller size if the logo already fits.
     calc() reasoning: 100vw minus the bar's left+right padding (16px
     each = 32px), minus the burger button's box (38px) and its gap
     from the logo (16px, the .tomo-nav gap value) = the real width
     budget left for the logo. height:auto keeps proportions intact
     (no squashing/distortion) — only the rendered size shrinks. */
  .tomo-logo-wrap,
  .tomo-nav-left {
    flex-shrink: 1;
    min-width: 0;
  }
  .tomo-logo-wrap .custom-logo-link .custom-logo,
  .tomo-logo-wrap .custom-logo-link img,
  .tomo-logo-wrap img {
    max-width: calc(100vw - 32px - 38px - 16px);
    width: auto;
    height: auto;
    /* Cap height so it can't render larger than the desktop 80px even
       on a wide phone in landscape, but allow it to shrink below that
       on narrow screens via the max-width constraint above. */
    max-height: 80px;
  }
  /* Body padding accounts for the taller nav. Bumped from 54px — the
     previous value was clipping page content under row 2 on real
     devices. If this still clips on yours, the number after
     "var(--nav-h) +" is the one to nudge further. */
  body.tomo-theme { padding-top: calc(var(--nav-h) + 76px); }

  /* Cart becomes a floating fixed button on mobile instead of sitting
     in the top bar — frees up the width it was taking in row 2 next
     to the scrollable category links, which was the actual room
     problem. Search + theme toggle are untouched, still in the top
     bar. position:fixed takes it out of .tomo-nav-right's flex flow
     automatically (fixed-position elements don't occupy space in
     their parent's layout), so no duplicate markup is needed — this
     is the SAME link element, just repositioned at this breakpoint. */
  .tomo-cart-link {
    position: fixed;
    bottom: 10px;
    right: 16px;
    z-index: 9998; /* below the 9999 nav bar, above normal page content */
    /* Circular icon-only button, matching the search/theme-toggle
       visual language, rather than the top bar's pill-with-text
       shape — a floating button reads better compact. */
    width: 50px; height: 50px;
    padding: 0;
    justify-content: center;
    border-radius: 50%;
    /* Light-mode shadow colour — var(--ink)'s light-mode value
       (#2e37fb) at 30% opacity, written as rgba() since CSS variables
       can't be substituted directly into rgba()'s colour channels.
       Dark mode override is just below (was previously missing
       entirely, which is why this stayed deep blue in both modes). */
    box-shadow: 0 4px 14px rgba(46,55,251,0.3);
  }
  [data-theme="dark"] .tomo-cart-link {
    /* var(--ink)'s dark-mode value (#9cd8f7, the pale blue) at the
       same 30% opacity as the light-mode shadow above. */
    box-shadow: 0 4px 14px rgba(156,216,247,0.3);
  }
  /* Text label hidden — icon + count badge only, floating. Visually
     hidden rather than removed from the DOM, so it's still announced
     to screen readers. */
  .tomo-cart-link span:not(.tomo-cart-count) {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    border: 0;
  }
  .tomo-cart-icon { width: 22px; height: 22px; }
  .tomo-cart-count {
    position: absolute;
    top: -2px; right: -2px;
  }
}

/* ─────────────────────────────────────────────────────────────────────
   MOBILE LOGO CENTERING (JS-driven)
   Applied only by initMobileLogoCenter() in main.js, only below the
   780px breakpoint, only after measuring the real rendered logo — so
   desktop's layout/behaviour above is completely untouched.

   .tomo-logo-mobile-centered switches the wrap from normal grid flow
   to an absolutely-positioned box spanning the full bar width, so it
   can be centered against the true viewport center rather than the
   left edge of its grid column. JS sets --tomo-logo-scale (a plain
   size multiplier, applied to the <img> and ::before's height/width —
   NOT a CSS transform: scale()) so the rendered artwork shrinks to
   fit while every drop-shadow ring above stays at its literal pixel
   thickness, exactly as on desktop. */
@media (max-width: 780px) {
  .tomo-nav.tomo-logo-mobile-centered {
    /* Row 1 no longer auto-sizes from the logo (it's out of flow now,
       position:absolute) — pin it to the same box the logo actually
       occupies (35px top margin + scaled height) so row 2 (links/
       search) doesn't ride up and overlap the floating logo. */
    grid-template-rows: calc(35px + 80px * var(--tomo-logo-scale, 1)) auto;
  }
  .tomo-logo-mobile-centered .tomo-logo-wrap {
    position: absolute;
    top: 0;
    /* left/width/margin-top are all set inline by JS per-measurement
       (see positionMobileLogo() in main.js) — this just establishes
       the positioning context and removes it from normal flow, so
       .tomo-nav-left (and the row-1 grid track) no longer need to
       reserve any width/height for the logo. */
    flex-shrink: 0;
  }
  .tomo-logo-mobile-centered .tomo-logo-wrap .custom-logo-link .custom-logo,
  .tomo-logo-mobile-centered .tomo-logo-wrap .custom-logo-link img,
  .tomo-logo-mobile-centered .tomo-logo-wrap img {
    /* Scale via real box height (not transform), so drop-shadow ring
       widths above stay literal/constant instead of scaling down
       with the artwork. */
    height: calc(80px * var(--tomo-logo-scale, 1));
    max-width: none;
    max-height: none;
  }
}

@media (min-width: 781px) {
  body.tomo-theme { padding-top: var(--nav-h); }
  .tomo-nav-burger { display: none !important; }
  .tomo-nav-mobile-links { display: none !important; }
}
/* ─────────────────────────────────────────────────────────────────────
   LOGO — the_custom_logo() outputs:
     <a class="custom-logo-link" href="/"><img class="custom-logo" …></a>
   inside <div class="tomo-logo-wrap">.

   The white ring + visible artwork render on the real <img> itself,
   sitting ABOVE the bar (z-index 2, inside .tomo-logo-wrap's stacking
   context, which is itself part of the normal page flow now — no
   longer forced to z-index 10000 on the wrapper, since only specific
   children need to be elevated, not the whole wrapper).

   The grey ring renders on a SEPARATE element — a ::before pseudo on
   .tomo-logo-wrap — duplicating the same logo image via
   background-image, with ONLY the grey-ring drop-shadow filter
   applied, sized to exactly match the real <img> via absolute
   positioning + inset:0. This pseudo sits at z-index 0, BELOW
   .tomo-nav::before (z-index 1, the bar's own white background), so
   the grey ring tucks behind the topbar — creating the illusion that
   the bar's own border continues into/behind the logo's outline,
   exactly as requested.

   This split was necessary because drop-shadow() filters paint as
   part of the SAME element they're applied to — a single <img> cannot
   have part of its filter stack behind one layer and part above
   another. Splitting the grey ring onto its own pseudo-element is the
   only way to give it independent stacking from the white ring/art.
   ───────────────────────────────────────────────────────────────────── */
.tomo-logo-wrap {
  display: flex;
  align-items: flex-end;
  position: relative;
  /* Standard position, +15px lower per request (20px -> 35px) */
  margin-top: 35px;
  /* Extra squash protection alongside .tomo-nav-left's flex-shrink:0 */
  flex-shrink: 0;
}

/* Grey ring — duplicate of the logo image, grey-ring filter only,
   sitting BEHIND the bar's background (.tomo-nav::before is z-index 1).
   Sized via inset:0 to exactly match the real <img>'s rendered box,
   so it tracks any responsive/mobile resizing automatically without
   needing to know the image's native pixel dimensions. */
.tomo-logo-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  /* Hints the browser to keep this element on its own compositing
     layer ahead of time, since its filter (the colour of the ring)
     changes on every dark-mode toggle — without this, a filter swap
     on a background-image this size can occasionally lag a frame or
     two behind the toggle itself, which is the "wrong colour sticks
     briefly" symptom.

     translateZ(0) forces a HARD layer promotion (will-change alone is
     only a hint the browser can ignore under memory pressure — mobile
     GPUs are exactly where that's most likely, which lines up with
     this glitch showing on mobile). contain:paint stops this layer's
     paint from being able to bleed into/read from neighbouring layers
     mid-render, and isolation:isolate gives the 8-shadow filter stack
     its own stacking context so it's resolved as one atomic unit
     rather than potentially compositing gradually alongside sibling
     layers. None of this changes anything visually when it's already
     working — it only changes how reliably the browser finishes the
     filter render before showing it. */
  will-change: filter;
  transform: translateZ(0);
  contain: paint;
  isolation: isolate;
  z-index: 0;
  pointer-events: none;
  background-image: url('https://shop.tomodatchi.net/wp-content/uploads/2025/03/tomodatchilogoo2-scaled.png');
  background-repeat: no-repeat;
  background-position: left bottom;
  background-size: contain;
  filter:
    /* grey ring — thickened to 1/3 more than before (4.57px literal,
       up from 3.43px; displays at ~10.7px vs the previous ~8px, same
       2.33x device-pixel ratio used elsewhere in this file). Diagonal
       component = 4.57 * cos(45deg) = 3.23px. Still 0px blur. */
    drop-shadow(4.57px  0.00px 0px #c8d8ec)
    drop-shadow(3.23px  3.23px 0px #c8d8ec)
    drop-shadow(0.00px  4.57px 0px #c8d8ec)
    drop-shadow(-3.23px  3.23px 0px #c8d8ec)
    drop-shadow(-4.57px  0.00px 0px #c8d8ec)
    drop-shadow(-3.23px -3.23px 0px #c8d8ec)
    drop-shadow(0.00px -4.57px 0px #c8d8ec)
    drop-shadow(3.23px -3.23px 0px #c8d8ec);
}
/* Briefly drops this layer off the GPU compositor — see
   initLogoOutlineRepaint() in main.js for why/when this class gets
   toggled. No visual difference from the rule above other than the
   transform value, since translateZ(0) vs none is not a visible
   change on its own. */
.tomo-logo-wrap.tomo-logo-repaint::before {
  transform: none;
}

/* WP's generated anchor — clean block, no inline gap */
.tomo-logo-wrap .custom-logo-link {
  display: block;
  line-height: 0;
  text-decoration: none;
  position: relative;
  /* Above .tomo-nav (z-index 9999) and the bar's background — this is
     the layer that now needs the high z-index, not the whole wrapper,
     since the grey-ring pseudo above deliberately stays low. */
  z-index: 10000;
}

/* The img itself — white ring only now (grey ring moved to the
   ::before pseudo above). An 8-point true-circle ring (equal radius
   at every angle) with a touch of antialiasing blur bridges the gaps
   between points so the edge reads as one solid stroke. */
.tomo-logo-wrap .custom-logo-link .custom-logo,
.tomo-logo-wrap .custom-logo-link img,
.tomo-logo-wrap img {
  display: block;
  height: 80px;
  width: auto;
  /* Override the global `img { max-width:100% }` reset and guarantee
     the logo never compresses horizontally at any viewport width. */
  max-width: none;
  flex-shrink: 0;
  position: relative;
  z-index: 2;
  /* Same compositing hint as .tomo-logo-wrap::before above — this
     element's filter (ring colour) also changes on dark-mode toggle.
     Same hard-layer-promotion + paint-containment reasoning as the
     ::before pseudo too: see the comment there for why translateZ(0)/
     contain/isolation are added alongside will-change. */
  will-change: filter;
  transform: translateZ(0);
  contain: paint;
  isolation: isolate;
  filter:
    /* white ring — radius 3px, blur cut from 0.4px to 0.1px (antialias-
       level only, just enough to bridge the 8 discrete shadow points
       into one stroke without a visible soft/fuzzy halo) */
    drop-shadow(3.00px  0.00px 0.1px #ffffff)
    drop-shadow(2.12px  2.12px 0.1px #ffffff)
    drop-shadow(0.00px  3.00px 0.1px #ffffff)
    drop-shadow(-2.12px  2.12px 0.1px #ffffff)
    drop-shadow(-3.00px  0.00px 0.1px #ffffff)
    drop-shadow(-2.12px -2.12px 0.1px #ffffff)
    drop-shadow(0.00px -3.00px 0.1px #ffffff)
    drop-shadow(2.12px -2.12px 0.1px #ffffff);
}
/* Same repaint-forcing class as .tomo-logo-wrap::before above,
   applied directly (this is a real element, not a pseudo, so JS can
   target it by class without needing the parent-selector trick). */
.tomo-logo-wrap img.tomo-logo-repaint,
.tomo-logo-wrap .custom-logo-link .custom-logo.tomo-logo-repaint {
  transform: none;
}

.tomo-logo-text-link { text-decoration: none; }
.tomo-logo-text {
  font-family: 'Fredoka', sans-serif; font-weight: 700; font-size: 1.05rem;
  color: var(--ink);
}

.tomo-nav-links { display: flex; gap: 2px; }
.tomo-nav-links a {
  font-family: 'Fredoka', sans-serif; font-size: 0.95rem; font-weight: 500;
  text-decoration: none; color: var(--muted);
  padding: 5px 14px; border-radius: 100px;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  display: inline-block;
  /* Idle state: white rounded pill, same shape/radius as the active
     blue pill below, with a faint border so it reads against the
     bar's own near-white background instead of disappearing into it. */
  background: #ffffff;
  border: 2px solid var(--border-soft);
}
.tomo-nav-links a:hover { background: var(--border-soft); color: var(--ink); }
.tomo-nav-links li.current-menu-item > a,
.tomo-nav-links a.active { background: var(--ink); color: #fff; }

/* Search — deep blue rounded button */
.tomo-nav-search { position: relative; display: flex; align-items: center; }
.tomo-nav-search input[type="search"] {
  font-family: 'Nunito', sans-serif; font-size: 0.85rem;
  width: 0; opacity: 0; padding: 0; border: none;
  background: var(--border-soft); border-radius: 100px;
  transition: width 0.25s ease, opacity 0.2s ease, padding 0.25s ease;
  height: 34px;
}
.tomo-nav-search.open input[type="search"] {
  width: 160px; opacity: 1; padding: 0 14px;
}
.tomo-nav-search button {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid var(--ink); background: var(--ink); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: #fff; transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.tomo-nav-search button:hover { background: #1c24d9; border-color: #1c24d9; }

/* Dark mode toggle — same 34px circular treatment as the search
   button right next to it, so the two read as a matched pair. */
.tomo-theme-toggle {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid var(--ink); background: var(--ink); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: #fff; transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.tomo-theme-toggle:hover { background: #1c24d9; border-color: #1c24d9; }
.tomo-theme-icon { display: block; }
.tomo-theme-icon-moon { display: none; }
[data-theme="dark"] .tomo-theme-icon-sun { display: none; }
[data-theme="dark"] .tomo-theme-icon-moon { display: block; }

/* Cart pill */
.tomo-cart-link {
  display: flex; align-items: center; gap: 7px;
  font-family: 'Fredoka', sans-serif; font-size: 0.85rem; font-weight: 600;
  background: var(--border-soft); border: 2px solid var(--border);
  border-radius: 100px; padding: 5px 14px 5px 10px;
  text-decoration: none; color: var(--ink);
  transition: background 0.15s, border-color 0.15s, transform 0.15s;
}
.tomo-cart-link:hover { background: var(--ink); color: #fff; border-color: var(--ink); transform: scale(1.04); }
.tomo-cart-icon { width: 18px; height: 18px; flex-shrink: 0; }
.tomo-cart-count {
  background: var(--ink); color: #fff;
  font-size: 0.68rem; font-weight: 700;
  min-width: 16px; height: 16px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 2px;
}
.tomo-cart-link:hover .tomo-cart-count { background: #fff; color: var(--ink); }

/* Lang toggle */
.lang-toggle {
  display: flex; align-items: center;
  background: var(--border-soft); border: 2px solid var(--border);
  border-radius: 100px; padding: 3px; gap: 0;
}
.lang-btn {
  font-family: 'Fredoka', sans-serif; font-size: 0.72rem; font-weight: 600;
  padding: 3px 10px; border-radius: 100px; border: none;
  background: transparent; cursor: pointer; color: var(--muted);
  transition: background 0.14s, color 0.14s; line-height: 1;
}
.lang-btn.active { background: var(--ink); color: #fff; }

/* Mobile nav toggle */
.tomo-nav-burger {
  display: none; width: 38px; height: 38px; border-radius: 50%;
  border: 2px solid var(--border); background: #fff; cursor: pointer;
  align-items: center; justify-content: center; color: var(--ink);
}

/* ─── PAGE WRAPPER ─── */
.tomo-shop-wrap {
  width: 100%;
  padding: 40px 36px 80px;
  max-width: 1400px;
  margin: 0 auto;
  /* Same class of fix as .tomo-browser-urlbar above — without this,
     a descendant's content (like the carousel's urlbar text) can
     force this wrapper, and therefore the whole page, wider than the
     viewport. box-sizing:border-box (set globally via the *,*::before
     rule near the top of this file) means padding is included in
     width:100%, so this stays exact at any viewport size. */
  overflow-x: hidden;
}
.tomo-shop-inner { width: 100%; }

.tomo-shop-layout {
  display: grid;
  /* minmax(0, ...) is the CSS Grid equivalent of flexbox's min-width:0
     fix used on .tomo-browser-urlbar — grid tracks have the exact same
     "won't shrink below content's natural width" default. Without the
     0 floor here, the 300px sidebar column (which contains the
     carousel) could still drag the 1fr main column wider than
     available space whenever its content's natural width exceeded
     300px, which is exactly what was happening with the urlbar text. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
  gap: 40px;
  align-items: start;
}
@media (max-width: 1000px) {
  .tomo-shop-layout { grid-template-columns: minmax(0, 1fr); }
}

/* Page heading band */
.tomo-page-head {
  text-align: center;
  padding: 12px 24px 36px;
}
.tomo-page-eyebrow {
  font-family: 'Fredoka', sans-serif; font-size: 0.78rem; font-weight: 500;
  color: var(--muted); letter-spacing: 0.1em; text-transform: uppercase;
  margin: 0 0 6px;
}
.tomo-page-title {
  font-family: 'Fredoka', sans-serif; font-size: 2.2rem; font-weight: 700;
  color: var(--ink); margin: 0;
}

/* ─── FOOTER ─── */
.tomo-footer {
  border-top: 2px solid var(--border-soft);
  padding: 28px 36px 36px;
  text-align: center;
  font-family: 'Fredoka', sans-serif; font-size: 0.8rem; color: var(--muted);
}
.tomo-footer a { text-decoration: none; color: var(--muted); }
.tomo-footer a:hover { color: var(--ink); }
.tomo-footer-links { display: flex; justify-content: center; gap: 18px; margin-bottom: 10px; flex-wrap: wrap; }

/* ─── BUTTONS (shared pill style) ─── */
.tomo-btn {
  font-family: 'Fredoka', sans-serif; font-size: 0.92rem; font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--ink); color: #fff !important;
  border: 2.5px solid var(--ink); border-radius: 100px;
  padding: 11px 26px; cursor: pointer;
  text-decoration: none !important;
  transition: background 0.15s, color 0.15s, transform 0.15s, box-shadow 0.18s;
  box-shadow: 0 4px 14px rgba(46,55,251,0.18);
}
.tomo-btn:hover { background: #1c24d9; transform: translateY(-1px); box-shadow: 0 8px 22px rgba(46,55,251,0.26); }
.tomo-btn:active { transform: translateY(0); }
.tomo-btn-outline {
  background: #fff; color: var(--ink) !important; border-color: var(--border);
  box-shadow: 0 4px 14px rgba(160,184,210,0.25);
}
.tomo-btn-outline:hover { background: var(--border-soft); border-color: var(--ink); }
.tomo-btn-block { width: 100%; }
.tomo-btn[disabled], .tomo-btn.disabled {
  opacity: 0.5; cursor: not-allowed; transform: none !important;
}

/* Generic blue-bordered "sticker card" panel */
.tomo-panel {
  background: #fff;
  border: var(--card-border-outer) solid var(--logo-blue);
  border-radius: var(--radius);
  box-shadow: 4px 5px 8px rgba(160,184,210,0.45);
  overflow: hidden;
}

/* Animations */
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
.anim { animation: fadeUp 0.42s cubic-bezier(0.22,1,0.36,1) both; }
.anim-d1 { animation-delay: 0.06s; }
.anim-d2 { animation-delay: 0.12s; }
.anim-d3 { animation-delay: 0.18s; }

@keyframes bgDriftStripes {
  from { background-position: 0 0; }
  to   { background-position: -28px 28px; }
}
@keyframes popOutline {
  0%   { filter: none; }
  40%  {
    filter:
      drop-shadow( 0px   3px 0px white) drop-shadow( 0px  -3px 0px white)
      drop-shadow( 3px   0px 0px white) drop-shadow(-3px   0px 0px white)
      drop-shadow( 2px   2px 0px white) drop-shadow(-2px   2px 0px white)
      drop-shadow( 2px  -2px 0px white) drop-shadow(-2px  -2px 0px white)
      drop-shadow(-4px   4px 0px #2e37fb);
  }
  100% {
    filter:
      drop-shadow( 0px   3px 0px white) drop-shadow( 0px  -3px 0px white)
      drop-shadow( 3px   0px 0px white) drop-shadow(-3px   0px 0px white)
      drop-shadow( 2px   2px 0px white) drop-shadow(-2px   2px 0px white)
      drop-shadow( 2px  -2px 0px white) drop-shadow(-2px  -2px 0px white)
      drop-shadow(-4px   4px 0px #2e37fb);
  }
}

/* ─── VARIANT PICKER DIALOGUE (visual novel style) ─── */
.tomo-vn-overlay {
  position: fixed; inset: 0;
  background: rgba(20,24,40,0.35);
  z-index: 19000;
  opacity: 0; pointer-events: none;
  transition: opacity 0.2s ease;
}
.tomo-vn-overlay.open { opacity: 1; pointer-events: all; }

.tomo-vn-panel {
  position: fixed;
  bottom: 40px;
  left: 50%; transform: translateX(-50%) translateY(20px);
  width: min(480px, 92vw);
  background: #fff;
  border: 6px solid var(--logo-blue);
  border-radius: 22px;
  box-shadow: 0 16px 48px rgba(46,55,251,0.22), 4px 5px 8px rgba(160,184,210,0.5);
  padding: 20px 22px 22px;
  z-index: 19001;
  opacity: 0;
  transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.22,1,0.36,1);
  pointer-events: none;
}
.tomo-vn-overlay.open .tomo-vn-panel {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: all;
}
.tomo-vn-title {
  font-family: 'Fredoka', sans-serif; font-size: 0.72rem; font-weight: 600;
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em;
  margin: 0 0 6px;
}
.tomo-vn-product-name {
  font-family: 'Fredoka', sans-serif; font-size: 1.05rem; font-weight: 700;
  color: var(--logo-blue); margin: 0 0 16px;
}
.tomo-vn-attr-label {
  font-family: 'Fredoka', sans-serif; font-size: 0.72rem; font-weight: 600;
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.07em;
  margin: 0 0 8px;
}
.tomo-vn-choices {
  display: flex; flex-direction: column; gap: 8px;
}
.tomo-vn-choice {
  font-family: 'Fredoka', sans-serif; font-size: 0.95rem; font-weight: 600;
  background: var(--border-soft); border: 2.5px solid var(--border);
  border-radius: 100px; padding: 10px 20px;
  cursor: pointer; color: var(--ink); text-align: left;
  transition: background 0.14s, border-color 0.14s, transform 0.14s;
  display: flex; align-items: center; gap: 10px;
}
.tomo-vn-choice::before {
  content: '▷';
  font-size: 0.75rem; color: var(--muted);
  flex-shrink: 0;
  transition: color 0.14s;
}
.tomo-vn-choice:hover {
  background: var(--ink); color: #fff; border-color: var(--ink);
  transform: translateX(4px);
}
.tomo-vn-choice:hover::before { color: rgba(255,255,255,0.7); }
.tomo-vn-choice.out-of-stock {
  opacity: 0.45; cursor: not-allowed; pointer-events: none;
}
.tomo-vn-close {
  position: absolute; top: 14px; right: 16px;
  width: 28px; height: 28px; border-radius: 50%;
  border: 2px solid var(--border); background: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 14px;
  transition: background 0.14s, color 0.14s;
}
.tomo-vn-close:hover { background: var(--border-soft); color: var(--ink); }

@media (max-width: 600px) {
  .tomo-shop-wrap { padding: 24px 16px 60px; }
  .tomo-page-title { font-size: 1.6rem; }
  .tomo-vn-panel { bottom: 16px; }
}
/* ─── DARK MODE: hardcoded-colour overrides ───
   A handful of selectors above use a literal #fff / rgba(255,255,255,…)
   instead of var(--bg) (mostly small chrome elements: pills, the nav's
   blur layer, buttons, toasts) — these don't repaint automatically from
   the [data-theme="dark"] variable block earlier in this file, so they
   get explicit overrides here instead. Kept in one place, rather than
   inline at each original rule, so the full set of dark-mode-specific
   colour decisions is easy to scan/maintain together. */
[data-theme="dark"] .tomo-nav::before {
  background: rgba(35,35,46,0.93);
}
[data-theme="dark"] .tomo-nav-links a {
  background: #2a2a38;
}
[data-theme="dark"] .tomo-cart-link:hover .tomo-cart-count {
  background: #2a2a38;
}
[data-theme="dark"] .tomo-nav-burger {
  background: #2a2a38;
}

/* Logo outline colours, dark mode only — same geometry/radius/blur as
   the light-mode rings above, only the colours change, sourced from
   the topbar itself so the rings still read as "the bar's own
   surfaces continuing into the logo":
     - the ring that sits ON the logo art (was white, #ffffff) now
       matches the topbar's own FILL colour (.tomo-nav::before
       background, dark mode = #23232e)
     - the ring that sits BEHIND the bar (was #c8d8ec, the light-mode
       value of var(--border)) now matches the topbar's DIVIDER LINE
       colour (.tomo-nav::before border-bottom, dark mode var(--border)
       = #3c3c4d) */
[data-theme="dark"] .tomo-logo-wrap::before {
  filter:
    drop-shadow(4.57px  0.00px 0px #3c3c4d)
    drop-shadow(3.23px  3.23px 0px #3c3c4d)
    drop-shadow(0.00px  4.57px 0px #3c3c4d)
    drop-shadow(-3.23px  3.23px 0px #3c3c4d)
    drop-shadow(-4.57px  0.00px 0px #3c3c4d)
    drop-shadow(-3.23px -3.23px 0px #3c3c4d)
    drop-shadow(0.00px -4.57px 0px #3c3c4d)
    drop-shadow(3.23px -3.23px 0px #3c3c4d);
}
[data-theme="dark"] .tomo-logo-wrap .custom-logo-link .custom-logo,
[data-theme="dark"] .tomo-logo-wrap .custom-logo-link img,
[data-theme="dark"] .tomo-logo-wrap img {
  filter:
    drop-shadow(3.00px  0.00px 0.1px #23232e)
    drop-shadow(2.12px  2.12px 0.1px #23232e)
    drop-shadow(0.00px  3.00px 0.1px #23232e)
    drop-shadow(-2.12px  2.12px 0.1px #23232e)
    drop-shadow(-3.00px  0.00px 0.1px #23232e)
    drop-shadow(-2.12px -2.12px 0.1px #23232e)
    drop-shadow(0.00px -3.00px 0.1px #23232e)
    drop-shadow(2.12px -2.12px 0.1px #23232e);
}
[data-theme="dark"] .tomo-btn-outline {
  background: #2a2a38;
}
[data-theme="dark"] .tomo-panel {
  background: #2a2a38;
}
[data-theme="dark"] .tomo-vn-panel {
  background: #2a2a38;
}
[data-theme="dark"] .tomo-vn-close {
  background: #2a2a38;
}
