/* ============================================================
   Muthu — the pearl theme and the design system on top of it
   ============================================================
   muthu (முத்து) is Tamil for pearl, which is the whole idea: a pale,
   luminous, slightly iridescent surface rather than the dark abyss this
   app used to open with. The dark variant is obsidian, not navy, and its
   iridescence comes from outlines rather than fills.

   This file loads after style.css and sits on top of it. That is
   deliberate: style.css carries six palettes that people may already
   have chosen and a thousand lines of working layout, and replacing all
   of it in one pass is how you break a working app. So the tokens here
   define a seventh palette, and the component rules below restyle the
   shell. Anyone who has explicitly chosen another palette keeps it -
   their [data-theme="..."] selector is more specific than :root.

   Rules for everything below:
     · Iridescence never goes under text. It lives in borders, rings,
       orbs and the kolam. Text sits on a surface with a measured
       contrast ratio, and the letters always win.
     · Blur is for the few, translucency for the many. backdrop-filter
       recomposites everything beneath it; there are fifteen cards on the
       path and only one nav bar.
     · Nothing is created under prefers-reduced-motion.
   ============================================================ */

/* ---------- the pearl palette ---------- */
:root[data-theme="muthu"], [data-theme="muthu"]{
  /* A pale theme has to work harder than a dark one to separate a card
     from the page. The first pass used a near-white page under near-white
     cards and the variety chooser simply disappeared - the cards were
     rendering, they just had nothing to stand against. The page is a step
     deeper now and the cards are nearly opaque white, so a surface reads
     as a surface before any border is drawn. */
  --paper:#EDF0F8;
  --paper-2:#E3E8F4;
  --card:rgba(255,255,255,.94);
  --card-solid:#FFFFFF;
  --ink:#141A2E;
  --ink-2:#33405E;
  --muted:#5A6580;
  --line:#CBD3E7;
  --gold:#C8790A;
  --gold-deep:#8A5205;
  --gold-shade:#A5650A;
  --on-gold:#2A1800;
  --teal:#0A7D45;
  --teal-shade:#075C33;
  --teal-soft:#E6F7EE;
  --teal-line:#B4E4C7;
  --on-teal:#FFFFFF;
  --red:#B02A1F;
  --red-soft:#FDEDEB;
  --red-line:#F2C4BE;
  --sea:#0C7F86;
  --sea-deep:#075F65;
  --sea-soft:#E4F3F4;
  --sea-line:#B5DEE1;
  --on-sea:#FFFFFF;
  --hero-a:#EFF1FB;
  --hero-b:#E7F2F4;
  --hero-line:#DCE2F2;
  --dot:rgba(20,26,46,.07);
  --glass:rgba(255,255,255,.62);
  --shadow:0 1px 2px rgba(20,26,46,.05), 0 16px 32px -20px rgba(20,26,46,.40);
  --shadow-lift:0 2px 4px rgba(20,26,46,.06), 0 28px 56px -22px rgba(20,26,46,.46);

  /* The four stops everything iridescent is built from. Pastel on
     purpose: these get multiplied over white, and anything stronger
     turns into a toy. */
  --holo-1:#CFC9F7;   /* lavender */
  --holo-2:#F7E6C6;   /* champagne */
  --holo-3:#CFEFE2;   /* mint */
  --holo-4:#BFE6EC;   /* sky teal */
  --holo-edge:rgba(255,255,255,.9);
  --lit:inset 0 1px 0 rgba(255,255,255,.85);
  /* How loud the kolam is, in one place. Pastel lines over white need
     more than neon lines over obsidian to read at all, so the two
     schemes are not the same number. Text always wins: these are set
     low enough that the figure is felt rather than read.

     The contrast audit cannot help here - it composites element
     backgrounds and has no idea there is an SVG layer behind the page -
     so this is judged by eye against the headings that sit directly on
     the paper rather than on a card. */
  --kolam-a:.42;
  --beast-a:.20;
}

/* ---------- obsidian ---------- */
@media (prefers-color-scheme: dark){
  :root[data-theme="muthu"]:not([data-scheme="light"]),
  [data-theme="muthu"]:not([data-scheme="light"]){
    --paper:#0A0E1C;
    --paper-2:#121829;
    --card:rgba(19,25,43,.72);
    --card-solid:#131B2B;
    --ink:#F3F6FF;
    --ink-2:#C3CCE4;
    --muted:#94A0C0;
    --line:#243049;
    --gold:#F2AE43;
    --gold-deep:#FFC36B;
    --gold-shade:#D6922A;
    --on-gold:#241700;
    --teal:#35CE74;
    --teal-shade:#2AA85E;
    --teal-soft:rgba(53,206,116,.12);
    --teal-line:rgba(53,206,116,.34);
    --on-teal:#04210F;
    --red:#FF8578;
    --red-soft:rgba(255,133,120,.12);
    --red-line:rgba(255,133,120,.34);
    --sea:#37D2DA;
    --sea-deep:#7BE6EC;
    --sea-soft:rgba(55,210,218,.12);
    --sea-line:rgba(55,210,218,.32);
    --on-sea:#042227;
    --hero-a:#141C32;
    --hero-b:#102A33;
    --hero-line:#26324C;
    --dot:rgba(255,255,255,.055);
    --glass:rgba(19,25,43,.6);
    --shadow:0 1px 0 rgba(0,0,0,.2), 0 18px 40px -22px rgba(0,0,0,.75);
    --shadow-lift:0 2px 0 rgba(0,0,0,.25), 0 30px 60px -26px rgba(0,0,0,.85);
    --holo-1:#A99BF5;
    --holo-2:#FFD38A;
    --holo-3:#86F0C8;
    --holo-4:#7FE3F0;
    --holo-edge:rgba(255,255,255,.14);
    --lit:inset 0 1px 0 rgba(255,255,255,.07);
    --kolam-a:.16;
  --beast-a:.17;
    --beast-a:.17;
  }
}
:root[data-theme="muthu"][data-scheme="dark"],
[data-theme="muthu"][data-scheme="dark"]{
  --paper:#0A0E1C;
  --paper-2:#121829;
  --card:rgba(19,25,43,.72);
  --card-solid:#131B2B;
  --ink:#F3F6FF;
  --ink-2:#C3CCE4;
  --muted:#94A0C0;
  --line:#243049;
  --gold:#F2AE43;
  --gold-deep:#FFC36B;
  --gold-shade:#D6922A;
  --on-gold:#241700;
  --teal:#35CE74;
  --teal-shade:#2AA85E;
  --teal-soft:rgba(53,206,116,.12);
  --teal-line:rgba(53,206,116,.34);
  --on-teal:#04210F;
  --red:#FF8578;
  --red-soft:rgba(255,133,120,.12);
  --red-line:rgba(255,133,120,.34);
  --sea:#37D2DA;
  --sea-deep:#7BE6EC;
  --sea-soft:rgba(55,210,218,.12);
  --sea-line:rgba(55,210,218,.32);
  --on-sea:#042227;
  --hero-a:#141C32;
  --hero-b:#102A33;
  --hero-line:#26324C;
  --dot:rgba(255,255,255,.055);
  --glass:rgba(19,25,43,.6);
  --shadow:0 1px 0 rgba(0,0,0,.2), 0 18px 40px -22px rgba(0,0,0,.75);
  --shadow-lift:0 2px 0 rgba(0,0,0,.25), 0 30px 60px -26px rgba(0,0,0,.85);
  --holo-1:#A99BF5;
  --holo-2:#FFD38A;
  --holo-3:#86F0C8;
  --holo-4:#7FE3F0;
  --holo-edge:rgba(255,255,255,.14);
  --lit:inset 0 1px 0 rgba(255,255,255,.07);
  --kolam-a:.16;
}

/* ---------- motion ---------- */
:root[data-theme="muthu"], [data-theme="muthu"]{
  /* One spring, used everywhere something is pressed. Overshoot is small
     on purpose: a letter learner taps a hundred times a session, and a
     bouncy button is charming twice and tiring after that. */
  --e-spring:cubic-bezier(.22,1.2,.36,1);
  --t-press:150ms;
}

/* ============================================================
   The ground: a pearl wash, and the kolam behind it
   ============================================================ */
[data-theme="muthu"] body{
  background-color:var(--paper);
  /* Three wide, very soft pools of the holographic stops. Each is under
     18% opacity, so they read as a sheen on the paper rather than as
     colour, and none of them sits where body text lands. */
  background-image:
    radial-gradient(118% 72% at 8% -8%,
      color-mix(in srgb, var(--holo-1) 42%, transparent) 0%, transparent 62%),
    radial-gradient(96% 58% at 102% 4%,
      color-mix(in srgb, var(--holo-4) 38%, transparent) 0%, transparent 58%),
    radial-gradient(120% 70% at 50% 108%,
      color-mix(in srgb, var(--holo-3) 34%, transparent) 0%, transparent 60%),
    radial-gradient(var(--dot) 1.1px, transparent 1.2px);
  background-size:auto, auto, auto, 24px 24px;
  background-position:0 0, 0 0, 0 0, -12px -12px;
  background-attachment:fixed, fixed, fixed, fixed;
}

/* The dreamscape: two layers of fixed vector art behind everything.
   Strictly inert - no pointer events, nothing focusable, nothing read
   out - and strictly behind, so no amount of drifting can ever land on
   top of a control. */
#kolam{
  position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden;
  contain:strict;                 /* its repaints cannot escape the layer */
}
#kolam .k-motif, #kolam .k-beast{
  position:absolute; transform:translate(-50%,-50%);
  animation-iteration-count:infinite;
  will-change:transform, opacity;
}
#kolam .k-motif{ animation-timing-function:ease-in-out; animation-direction:alternate }
#kolam .k-beast{ animation-timing-function:linear }
#kolam svg{ width:100%; height:100%; display:block; overflow:visible }

/* Layer 1, kolam: a line of uniform width, as rice flour trailed from
   the hand is. */
#kolam .k-motif{ animation-name:k-drift; opacity:var(--kolam-a, .3) }
#kolam .k-motif circle, #kolam .k-motif path{
  fill:none; stroke:currentColor; stroke-width:3;
  stroke-linejoin:round; stroke-linecap:round;
}
#kolam .k-motif .kf{ fill:currentColor; stroke:none }
#kolam .k-motif{ color:var(--sea) }

/* Layer 2, the animals: watermarks. Filled very faintly with a thin
   outline, which is what keeps them legible as shapes at this opacity
   without ever becoming objects on the page. */
#kolam .k-beast{ opacity:0; color:var(--sea) }
#kolam .k-beast.go-right{ animation-name:k-cross-right }
#kolam .k-beast.go-left { animation-name:k-cross-left }
/* Solid, not wireframe.

   These were a layer at 0.11 opacity holding shapes filled at 0.55 and
   outlined with a 1.2px hairline - about six percent in the end, which
   on a dark ground is exactly the thin scratchy outline that reads as
   an insect rather than an elephant. The fill is solid now and the one
   opacity that remains is the layer's, so the number in the stylesheet
   is the number on the screen. The hairline outlines are gone; the
   strokes that are left are the ones that are structural - a trunk, a
   pair of horns, stripes, a tail. */
#kolam .k-beast ellipse, #kolam .k-beast rect,
#kolam .k-beast circle, #kolam .k-beast path{
  fill:currentColor; stroke:none;
}
#kolam .k-beast .ks{
  fill:none; stroke:currentColor; stroke-linecap:round; stroke-linejoin:round;
}
/* Not all one colour: sapphire, teal and indigo off the same shell. */
#kolam .k-beast.tint-sea   { color:var(--sea) }
#kolam .k-beast.tint-teal  { color:var(--crab-olive) }
#kolam .k-beast.tint-indigo{ color:#5B4BD6 }

/* Very slow, so a shape appears to wander in and out of a view rather
   than to loop. Transform only - the compositor does all of it. */
@keyframes k-drift{
  from{ transform:translate(-50%,-50%) translate3d(-10px, -8px, 0) rotate(-5deg) }
  to  { transform:translate(-50%,-50%) translate3d(10px, 8px, 0) rotate(5deg) }
}
/* A crossing. Starts clear of the screen, fades up, walks the full
   width with a slow rise, fades out before the far edge. One direction
   only - alternate would make them pace back and forth like something
   in a cage. Transform and opacity, so the compositor owns all of it. */
@keyframes k-cross-right{
  0%   { transform:translate(-50%,-50%) translate3d(-18vw, 4vh, 0) scale(.94); opacity:0 }
  10%  { opacity:var(--beast-a, .13) }
  90%  { opacity:var(--beast-a, .13) }
  100% { transform:translate(-50%,-50%) translate3d(118vw, -4vh, 0) scale(1.06); opacity:0 }
}
@keyframes k-cross-left{
  0%   { transform:translate(-50%,-50%) translate3d(118vw, -3vh, 0) scale(1.06); opacity:0 }
  10%  { opacity:var(--beast-a, .13) }
  90%  { opacity:var(--beast-a, .13) }
  100% { transform:translate(-50%,-50%) translate3d(-18vw, 5vh, 0) scale(.94); opacity:0 }
}

#app{ position:relative; z-index:1 }

/* ============================================================
   Surfaces
   ============================================================ */

/* A holographic hairline, done as two stacked backgrounds: the card
   colour clipped to the padding box, the gradient clipped to the border
   box. One element, no pseudo-element, no extra paint. */
[data-theme="muthu"] .card,
[data-theme="muthu"] .unit,
[data-theme="muthu"] .fc-face,
[data-theme="muthu"] .opt,
[data-theme="muthu"] .variety,
[data-theme="muthu"] .wordcard,
[data-theme="muthu"] .hero{
  border:1px solid transparent;
  background-image:
    linear-gradient(var(--card), var(--card)),
    linear-gradient(118deg, var(--holo-1), var(--holo-2) 28%, var(--holo-3) 58%, var(--holo-4));
  background-origin:border-box;
  background-clip:padding-box, border-box;
  background-size:100% 100%, 220% 220%;
  background-position:0 0, 0% 50%;
  box-shadow:var(--shadow), var(--lit);
  transition:transform var(--t-press) var(--e-spring),
             box-shadow var(--t-2) var(--e-out),
             background-position 620ms var(--e-out);
}
/* The light catches the edge as you touch it - the gradient slides,
   nothing re-renders. */
[data-theme="muthu"] .unit:active,
[data-theme="muthu"] .opt:active,
[data-theme="muthu"] .variety:active,
[data-theme="muthu"] .card:active{ background-position:0 0, 100% 50% }
[data-theme="muthu"] .unit:active,
[data-theme="muthu"] .variety:active,
[data-theme="muthu"] .opt:active{ transform:scale(.975) }

@media (hover:hover){
  [data-theme="muthu"] .unit:hover,
  [data-theme="muthu"] .variety:hover,
  [data-theme="muthu"] .opt:hover{
    background-position:0 0, 100% 50%;
    box-shadow:var(--shadow-lift), var(--lit);
  }
}

/* ============================================================
   Buttons: pill, liquid, pressed
   ============================================================ */
[data-theme="muthu"] .btn{
  border-radius:999px;
  min-height:56px;
  font-weight:800;
  letter-spacing:.1px;
  border:1px solid transparent;
  box-shadow:var(--shadow), var(--lit);
  transition:transform var(--t-press) var(--e-spring),
             box-shadow var(--t-2) var(--e-out),
             filter var(--t-2) var(--e-out);
}
[data-theme="muthu"] .btn.sm{ min-height:48px; border-radius:999px }
/* The app already has a button system: gold is the primary action, teal
   is the affirmative one, ghost is the quiet one. This gives each of them
   a gradient, a pill and a spring - it does not re-colour them. The first
   version painted teal over every button while leaving the text white,
   which rendered fine and would have fallen back to white-on-gold at
   3.39:1 the moment the gradient did not paint. background-color is set
   to the same base hue underneath for exactly that reason. */
[data-theme="muthu"] .btn:not(.ghost){
  background-color:var(--gold);
  background-image:linear-gradient(135deg,
    var(--gold) 0%,
    color-mix(in srgb, var(--gold) 82%, var(--holo-2) 18%) 100%);
  color:var(--on-gold);
  box-shadow:var(--shadow-lift),
             inset 0 1px 0 color-mix(in srgb, var(--holo-edge) 55%, transparent);
}
[data-theme="muthu"] .btn.teal:not(.ghost){
  background-color:var(--teal);
  background-image:linear-gradient(135deg,
    var(--teal) 0%,
    color-mix(in srgb, var(--teal) 86%, var(--holo-3) 14%) 100%);
  color:var(--on-teal);
}
[data-theme="muthu"] .btn.ghost{
  background-image:
    linear-gradient(var(--card), var(--card)),
    linear-gradient(118deg, var(--holo-1), var(--holo-3) 55%, var(--holo-4));
  background-origin:border-box;
  background-clip:padding-box, border-box;
  color:var(--ink);
}
[data-theme="muthu"] .btn:active{ transform:translateY(1px) scale(.965) }

/* Chips and badges are facts, not buttons: smaller, quieter, still round. */
[data-theme="muthu"] .pill,
[data-theme="muthu"] .chip{
  border-radius:999px;
  transition:transform var(--t-press) var(--e-spring);
}
[data-theme="muthu"] .chip:active{ transform:scale(.94) }

/* A liquid ripple on touch. One element, removed when it finishes, and
   never created under reduced motion. */
.ripple{
  position:absolute; border-radius:50%; pointer-events:none;
  transform:translate(-50%,-50%) scale(0);
  background:radial-gradient(circle,
    color-mix(in srgb, var(--holo-edge) 70%, transparent) 0%,
    transparent 70%);
  animation:ripple-out 520ms var(--e-out) forwards;
  z-index:2;
}
@keyframes ripple-out{
  from{ transform:translate(-50%,-50%) scale(0); opacity:.85 }
  to  { transform:translate(-50%,-50%) scale(1); opacity:0 }
}

/* ============================================================
   The floating nav capsule
   ============================================================
   Five tabs, one gliding pill. The pill is a single element that
   translates, rather than five backgrounds fading in and out - so the
   movement is one compositor transform and it reads as the highlight
   travelling with your thumb.
   ============================================================ */
/* The capsule markup is in index.html for every palette, not just this
   one, so its LAYOUT cannot be scoped to muthu - only its decoration.
   Scoping both is exactly what I did first, and on the other six themes
   #tabbar kept its five-column grid while holding a single child, so all
   five tabs stacked at the same 202px position on top of one another.
   Measured, not noticed: the links overlapped on iravu, mayil and
   suvadi and were fine on muthu.

   Structure for everyone; the glass, the pill and the colour stay below
   under [data-theme="muthu"]. */
#tabbar{ display:flex; justify-content:center }
#tabbar .tab-capsule{
  position:relative; width:100%;
  display:grid; grid-template-columns:repeat(5, minmax(56px, 1fr));
}
#tabbar .tab-pill{ display:none }
[data-theme="muthu"] #tabbar .tab-pill{ display:block }

[data-theme="muthu"] #tabbar{
  inset:auto 0 0 0;
  background:none;
  border-top:0;
  backdrop-filter:none;
  -webkit-backdrop-filter:none;
  display:flex; justify-content:center;
  padding:0 12px calc(10px + env(safe-area-inset-bottom));
  pointer-events:none;              /* the capsule inside takes the taps */
}
[data-theme="muthu"] #tabbar .tab-capsule{
  pointer-events:auto;
  position:relative;
  display:grid; grid-template-columns:repeat(5, minmax(56px, 1fr));
  width:100%; max-width:430px;
  padding:6px;
  border-radius:999px;
  border:1px solid transparent;
  background-image:
    linear-gradient(color-mix(in srgb, var(--card-solid) 72%, transparent),
                    color-mix(in srgb, var(--card-solid) 72%, transparent)),
    linear-gradient(118deg, var(--holo-1), var(--holo-2) 30%, var(--holo-3) 62%, var(--holo-4));
  background-origin:border-box;
  background-clip:padding-box, border-box;
  /* The one place blur is worth paying for: it is a single element and it
     sits over everything that scrolls under it. */
  -webkit-backdrop-filter:blur(20px) saturate(150%);
  backdrop-filter:blur(20px) saturate(150%);
  box-shadow:0 18px 40px -18px rgba(20,26,46,.45), var(--lit);
}
[data-theme="muthu"] #tabbar .tab-pill{
  position:absolute; top:6px; left:6px;
  width:calc((100% - 12px) / 5);
  height:calc(100% - 12px);
  border-radius:999px;
  background-image:linear-gradient(125deg,
    color-mix(in srgb, var(--holo-1) 72%, transparent),
    color-mix(in srgb, var(--holo-4) 72%, transparent));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.5),
             0 6px 16px -8px color-mix(in srgb, var(--sea) 55%, transparent);
  transform:translateX(0);
  transition:transform 420ms var(--e-spring);
  z-index:0;
}
[data-theme="muthu"] #tabbar a{
  position:relative; z-index:1;
  height:52px; min-height:48px;
  border-radius:999px;
  gap:3px;
  color:var(--muted);
  transition:color var(--t-2) var(--e-out), transform var(--t-press) var(--e-spring);
}
[data-theme="muthu"] #tabbar a span{ font-size:19px; line-height:1 }
[data-theme="muthu"] #tabbar a.on{ color:var(--sea-deep); font-weight:800 }
[data-theme="muthu"] #tabbar a:active{ transform:scale(.92) }
[data-theme="muthu"] #tabbar em{ top:6px; right:calc(50% - 20px) }

/* The page has to clear the floating bar rather than tuck under it. */
[data-theme="muthu"] #app{ padding-bottom:calc(104px + env(safe-area-inset-bottom)) }

/* ============================================================
   Breathing room
   ============================================================ */
[data-theme="muthu"] .card{ padding:28px 24px; border-radius:30px; margin-bottom:var(--s-4) }
[data-theme="muthu"] .card.center{ padding:32px 24px }
[data-theme="muthu"] .unit{ padding:20px 22px; border-radius:26px }
[data-theme="muthu"] .variety{ padding:20px 22px; border-radius:26px; margin-bottom:var(--s-3) }
[data-theme="muthu"] .hero{ border-radius:32px; padding:32px 26px }
[data-theme="muthu"] .opt{ border-radius:22px; padding:18px 20px }
[data-theme="muthu"] .h2{ margin-top:var(--s-5); margin-bottom:var(--s-3) }

/* Every target a thumb has to find is at least 48px. */
[data-theme="muthu"] .btn,
[data-theme="muthu"] .btn.sm,
[data-theme="muthu"] .chip,
[data-theme="muthu"] .icon-btn,
[data-theme="muthu"] #tabbar a{ min-height:48px }
[data-theme="muthu"] .icon-btn{ min-width:48px }

/* ============================================================
   Nothing moves if the device says not to
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  #kolam svg, #kolam svg *{ animation:none !important }
  [data-theme="muthu"] #tabbar .tab-pill{ transition:none }
  .ripple{ display:none }
}

/* ============================================================
   The kolam's own animation
   ============================================================
   All of it is CSS on a built-once SVG: three rotations at different
   speeds, the middle ring counter-turning, and the gradient stops
   cycling through the four holographic colours. No script runs per
   frame.
   ============================================================ */









/* ============================================================
   The path, as a map
   ============================================================
   Each orb carries three things at once: which letter the unit is
   about, how far through it you are, and whether it is where you are
   standing now. The ring is a conic gradient driven by --p, which ui.js
   sets from the spaced-repetition record, so it is the real number.
   ============================================================ */
[data-theme="muthu"] .unit .bubble{
  width:66px; height:66px; flex:0 0 66px;
  border-radius:50%;
  position:relative; isolation:isolate;
  font-size:28px;
  border:0;
  background-image:linear-gradient(145deg,
    color-mix(in srgb, var(--card-solid) 92%, var(--holo-1) 8%),
    color-mix(in srgb, var(--card-solid) 92%, var(--holo-4) 8%));
  box-shadow:0 10px 22px -14px rgba(20,26,46,.6), var(--lit);
}
/* The ring: a conic sweep clipped to an annulus by a radial mask. One
   element, no SVG, nothing to keep in sync with the orb. */
[data-theme="muthu"] .unit .bubble::before{
  content:''; position:absolute; inset:-6px; border-radius:50%; z-index:-1;
  background:conic-gradient(from -90deg,
    var(--sea) calc(var(--p, 0) * 360deg),
    color-mix(in srgb, var(--line) 85%, transparent) 0);
  -webkit-mask:radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px));
          mask:radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px));
}
[data-theme="muthu"] .unit.done .bubble{
  color:var(--on-teal);
  background-image:linear-gradient(145deg, var(--teal), var(--teal-shade));
}
[data-theme="muthu"] .unit.done .bubble::before{
  background:var(--teal);
}
[data-theme="muthu"] .unit.next .bubble{
  color:var(--on-gold);
  background-image:linear-gradient(145deg, var(--gold), var(--gold-shade));
}
/* Where you are now, breathing. A box-shadow spread, which the
   compositor handles, and which stops when the device asks for less. */
[data-theme="muthu"] .unit.next .bubble{ animation:orb-breathe 2.8s var(--e-out) infinite }
@keyframes orb-breathe{
  0%,100%{ box-shadow:0 10px 22px -14px rgba(20,26,46,.6),
                      0 0 0 0 color-mix(in srgb, var(--gold) 55%, transparent) }
  55%    { box-shadow:0 10px 22px -14px rgba(20,26,46,.6),
                      0 0 0 12px color-mix(in srgb, var(--gold) 0%, transparent) }
}
/* A locked unit is dimmed by its own parts rather than by dropping the
   opacity of the whole row, which took the text down with it. */
[data-theme="muthu"] .unit.locked{ opacity:1 }
[data-theme="muthu"] .unit.locked .bubble,
[data-theme="muthu"] .unit.paid .bubble{
  color:var(--muted);
  background-image:linear-gradient(145deg, var(--paper-2), var(--paper-2));
  box-shadow:inset 0 0 0 1px var(--line);
  animation:none;
}
[data-theme="muthu"] .unit.locked .t, [data-theme="muthu"] .unit.paid .t{ opacity:.7 }

/* The thread between orbs is a line of pulli - the same dot the app
   teaches. It has to meet the new orb centre: 22px of padding plus half
   of a 66px orb. */
[data-theme="muthu"] .kolam .unit{ margin-bottom:36px }
[data-theme="muthu"] .kolam .unit::after{
  left:53px; width:4px; height:34px; top:calc(100% + 2px);
  background-size:4px 11px;
}
[data-theme="muthu"] .kolam .unit.done::after{ color:var(--teal) }
[data-theme="muthu"] .kolam .unit.next::after{ color:var(--gold) }

[data-theme="muthu"] .unit .stars{
  margin-top:5px; font-size:13px; letter-spacing:2px; line-height:1;
  color:var(--gold-deep);
}

@media (prefers-reduced-motion: reduce){
  [data-theme="muthu"] .unit.next .bubble{ animation:none }
}

/* ============================================================
   The blue crab accents
   ============================================================
   Atlantic blue crab: sapphire shell, coral claw tips, olive-teal in
   the joints. Mapped onto meanings this app already had rather than
   added on top of them.

     sapphire  anything you touch - buttons, the active tab, progress
     coral     attention - a streak, something due, a milestone
     olive     structure - secondary text, borders, rules
     gold      kept, and only for what you are working towards
     green     kept, and only for success

   One deliberate exception to the brief: it asked for coral on success
   alerts too. Coral at #FF3B30 is the same red the app uses for a wrong
   answer, and a colour that means both "right" and "wrong" is worse
   than no system at all. Success stays green; coral means look here.

   Sapphire replaces --sea rather than sitting beside it, because --sea
   is already the app's token for anything interactive - so one swap
   reaches every button, ring and highlight at once.

   Dark mode cannot use the same blues. #0066CC on obsidian is 2.3:1,
   which is unreadable; the dark scheme uses the lighter end of the
   shell instead.
   ============================================================ */
:root[data-theme="muthu"], [data-theme="muthu"]{
  --sea:#0066CC;
  --sea-deep:#004B87;
  --sea-soft:#E8F1FB;
  --sea-line:#B9D5F0;
  --on-sea:#FFFFFF;

  --crab-coral:#E0362C;        /* #FF3B30 is only 3.1:1 on white; this is
                                  the same hue taken to AA */
  --crab-coral-bright:#FF6B35; /* for fills, where text is not on top */
  --on-coral:#FFFFFF;
  --crab-olive:#2A6F97;
  --crab-olive-deep:#1F556F;

  --muted:#2A6F97;
  --line:#C6D4E2;
}

@media (prefers-color-scheme: dark){
  :root[data-theme="muthu"]:not([data-scheme="light"]),
  [data-theme="muthu"]:not([data-scheme="light"]){
    --sea:#4DA6FF;
    --sea-deep:#8CC6FF;
    --sea-soft:rgba(77,166,255,.13);
    --sea-line:rgba(77,166,255,.34);
    --on-sea:#04203D;
    --crab-coral:#FF8A7A;
    --crab-coral-bright:#FF7A45;
    --on-coral:#3A0C05;
    --crab-olive:#7FAFCE;
    --crab-olive-deep:#A8CCE4;
    --muted:#8FB2CB;
    --line:#223449;
  }
}
:root[data-theme="muthu"][data-scheme="dark"],
[data-theme="muthu"][data-scheme="dark"]{
  --sea:#4DA6FF;
  --sea-deep:#8CC6FF;
  --sea-soft:rgba(77,166,255,.13);
  --sea-line:rgba(77,166,255,.34);
  --on-sea:#04203D;
  --crab-coral:#FF8A7A;
  --crab-coral-bright:#FF7A45;
  --on-coral:#3A0C05;
  --crab-olive:#7FAFCE;
  --crab-olive-deep:#A8CCE4;
  --muted:#8FB2CB;
  --line:#223449;
}

/* ---- sapphire: anything you touch ---- */
[data-theme="muthu"] .btn:not(.ghost):not(.teal){
  background-color:var(--sea);
  background-image:linear-gradient(135deg, var(--sea) 0%, var(--sea-deep) 100%);
  color:var(--on-sea);
}
[data-theme="muthu"] #tabbar .tab-pill{
  background-image:linear-gradient(125deg,
    color-mix(in srgb, var(--sea) 20%, transparent),
    color-mix(in srgb, var(--sea) 34%, transparent));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.4),
             0 6px 16px -8px color-mix(in srgb, var(--sea) 60%, transparent);
}
[data-theme="muthu"] #tabbar a.on{ color:var(--sea-deep) }

/* ---- coral: look here ---- */
[data-theme="muthu"] #tabbar em{
  background:var(--crab-coral-bright);
  box-shadow:0 0 0 2px var(--card-solid),
             0 0 10px -1px color-mix(in srgb, var(--crab-coral-bright) 70%, transparent);
}
/* The streak is the one number in the app that rewards coming back, so
   it is the one number that gets the claw tip. */
[data-theme="muthu"] .stat.streak b,
[data-theme="muthu"] .streak-n{ color:var(--crab-coral) }

/* ---- olive: structure ---- */
[data-theme="muthu"] hr,
[data-theme="muthu"] .rule{
  border-color:color-mix(in srgb, var(--crab-olive) 28%, transparent);
}

/* Two things the audit caught after the crab accents went in.

   The orbs had a gradient and no background-color, so the glyph was
   measured - correctly - as white on white: 1.11:1. It rendered fine and
   would have been invisible the moment the gradient did not paint. Same
   mistake as the buttons, so the same fix: state the base colour.

   And olive at #2A6F97 measured 4.48:1 for secondary text, which is
   under AA by two hundredths. Same hue, taken down until it passes. */
[data-theme="muthu"] .unit .bubble{ background-color:var(--card-solid) }
[data-theme="muthu"] .unit.done .bubble{ background-color:var(--teal) }
[data-theme="muthu"] .unit.next .bubble{ background-color:var(--gold) }
[data-theme="muthu"] .unit.locked .bubble,
[data-theme="muthu"] .unit.paid .bubble{ background-color:var(--paper-2) }

:root[data-theme="muthu"], [data-theme="muthu"]{
  --crab-olive:#26658A;
  --muted:#26658A;
}

/* ============================================================
   Review, Chart, Stories, Write
   ============================================================ */

/* ---- Review: the card as an object ----
   The flip, the drag and the edge lighting were already here and already
   right - a real rotateY on a preserve-3d parent, not a crossfade. This
   only dresses them: glass faces, a holographic rim, and the swipe
   verdicts moved onto the crab accents. Green still means knew it, coral
   means not yet - deliberately not the same red as a wrong answer in a
   quiz, because failing to recall is not the same as being wrong. */
[data-theme="muthu"] .fc-face{
  border-radius:30px;
  padding:34px 24px;
  background-color:var(--card-solid);
  background-image:
    linear-gradient(var(--card), var(--card)),
    linear-gradient(118deg, var(--holo-1), var(--holo-2) 30%, var(--holo-3) 62%, var(--holo-4));
  background-origin:border-box;
  background-clip:padding-box, border-box;
  border:1px solid transparent;
  box-shadow:var(--shadow-lift), var(--lit);
}
[data-theme="muthu"] .fc-glyph{ font-size:96px }
[data-theme="muthu"] .fc.fc-yes .fc-face{
  border-color:transparent;
  box-shadow:0 0 0 3px color-mix(in srgb, var(--teal) 55%, transparent),
             0 0 34px -6px color-mix(in srgb, var(--teal) 50%, transparent);
}
[data-theme="muthu"] .fc.fc-no .fc-face{
  border-color:transparent;
  box-shadow:0 0 0 3px color-mix(in srgb, var(--crab-coral-bright) 55%, transparent),
             0 0 34px -6px color-mix(in srgb, var(--crab-coral-bright) 50%, transparent);
}
[data-theme="muthu"] .fc-actions{ gap:12px; margin-top:20px }

/* ---- Chart: tiles you can feel ---- */
[data-theme="muthu"] table.chart{ border-spacing:5px }
[data-theme="muthu"] table.chart td{
  border-radius:14px;
  background-color:var(--card-solid);
  background-image:linear-gradient(150deg,
    color-mix(in srgb, var(--card-solid) 94%, var(--holo-1) 6%),
    color-mix(in srgb, var(--card-solid) 94%, var(--holo-4) 6%));
  box-shadow:0 2px 6px -4px rgba(20,26,46,.45), var(--lit);
  transition:transform var(--t-press) var(--e-spring),
             box-shadow var(--t-2) var(--e-out);
}
[data-theme="muthu"] table.chart td:active{ transform:scale(.9) }
[data-theme="muthu"] table.chart td.hl{
  background-image:linear-gradient(150deg, var(--sea), var(--sea-deep));
  color:var(--on-sea);
  box-shadow:0 8px 20px -10px color-mix(in srgb, var(--sea) 70%, transparent);
}
[data-theme="muthu"] table.chart th{ color:var(--muted) }

/* ---- the drawer ---- */
[data-theme="muthu"] .sheet{
  border-top-left-radius:34px; border-top-right-radius:34px;
  background-color:color-mix(in srgb, var(--card-solid) 88%, transparent);
  -webkit-backdrop-filter:blur(26px) saturate(150%);
          backdrop-filter:blur(26px) saturate(150%);
  border-top:1px solid color-mix(in srgb, var(--holo-1) 50%, transparent);
  box-shadow:0 -22px 60px -24px rgba(10,14,28,.75), var(--lit);
}
/* A handle, because a sheet that can be dismissed should look like it. */
[data-theme="muthu"] .sheet::before{
  content:''; display:block; width:42px; height:4px; border-radius:4px;
  margin:2px auto 12px;
  background:color-mix(in srgb, var(--muted) 45%, transparent);
}

/* ---- Stories: a page, not a form ----
   The size control, the line focus and tap-to-translate were already
   built. This gives the reader the room it needed. */
[data-theme="muthu"] .sline{
  padding:14px 10px; border-radius:18px;
  transition:background-color var(--t-2) var(--e-out), opacity var(--t-2) var(--e-out);
}
[data-theme="muthu"] .sline.focus{
  background:color-mix(in srgb, var(--sea) 9%, transparent);
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--sea) 22%, transparent);
}
[data-theme="muthu"] .sline.dim{ opacity:.34 }
[data-theme="muthu"] .snum{
  color:var(--muted); font-variant-numeric:tabular-nums;
  min-width:26px; font-weight:800;
}
[data-theme="muthu"] .sizer{
  display:flex; align-items:center; gap:10px; justify-content:flex-end;
  margin-top:12px;
}
[data-theme="muthu"] .sizer .btn.sm{ width:auto; min-width:56px; padding:10px 16px }

/* ---- Write: the pad gets its lines ----
   A headline, a baseline and a centre to hang the letter on. Faint
   enough to be guidance and not a grid to colour inside. */
[data-theme="muthu"] .trace-box{
  border:1px solid transparent;
  border-radius:30px;
  background-color:var(--card-solid);
  background-image:
    linear-gradient(var(--card-solid), var(--card-solid)),
    linear-gradient(118deg, var(--holo-1), var(--holo-3) 55%, var(--holo-4));
  background-origin:border-box;
  background-clip:padding-box, border-box;
  box-shadow:var(--shadow-lift), var(--lit);
}
.trace-box .rule-lines{
  background-image:
    linear-gradient(to right,
      color-mix(in srgb, var(--muted) 26%, transparent) 50%, transparent 0),
    linear-gradient(to bottom,
      color-mix(in srgb, var(--muted) 22%, transparent) 50%, transparent 0),
    linear-gradient(to bottom,
      color-mix(in srgb, var(--muted) 22%, transparent) 50%, transparent 0);
  background-repeat:repeat-x, repeat-y, repeat-y;
  background-size:10px 1px, 1px 9px, 1px 9px;
  background-position:0 50%, 50% 0, 50% 0;
  z-index:0;
}
/* The vertical centre is one line, so the second horizontal is drawn
   separately rather than trying to coax three positions out of two
   gradients. */
.trace-box .rule-lines::after{
  content:''; position:absolute; left:0; right:0; top:22%;
  border-top:1px dashed color-mix(in srgb, var(--muted) 20%, transparent);
}
.trace-box .rule-lines::before{
  content:''; position:absolute; left:0; right:0; bottom:22%;
  border-top:1px dashed color-mix(in srgb, var(--muted) 20%, transparent);
}
[data-theme="muthu"] .score-ring{
  font-size:16px; font-weight:800; letter-spacing:.2px;
}
[data-theme="muthu"] .score-ring.good{ color:var(--teal-shade) }
[data-theme="muthu"] .score-ring.poor{ color:var(--crab-coral) }

/* A mark drawn by the composer comes back as an image sized to its own
   ink, so it needs holding to the line of the text around it. */
.sign-img{ display:inline-block; vertical-align:middle; max-width:100%; height:auto }
[data-theme="muthu"] .unit .bubble .sign-img{ max-height:34px; width:auto }
[data-theme="muthu"] table.chart th .sign-img{ max-height:20px; width:auto; margin:0 auto }
