/* ============================================================================
   TODAY - the blank slate, the level bar, and the bunny that carries your load.

   Same visual language as index.html and about.html: gothic blue-black with
   pink as the promise, drifting fog, everything motion-guarded.

   :WHY? THIS IS A SEPARATE STYLESHEET, NOT AN INLINE <style> BLOCK. app.html
   already carries ~250 lines of inline CSS and is the file nobody wants to
   touch. Keeping today's stylesheet outside the page means a colour or
   contrast fix here can never edit a byte of the severity-engine markup.
   ========================================================================== */

:root{
  --bg1:#04060b; --bg2:#0c1526; --bg3:#152450;
  --ink:#e8ecf5;
  /* :WHY? --dim IS .72, NOT THE .55 USED ON THE LANDING. Landing copy is short
     and decorative; this page is a working surface with real reading in it.
     At .55 the composite is 5.4:1 on the darkest band but only 4.1:1 against
     the lighter #152450 top of the gradient, which fails AA. .72 measures
     6.9:1 against that same worst-case band. */
  --dim:rgba(232,236,245,.72);
  --pink:#ff5fa2; --pink-soft:#ffb6d5; --pink-deep:#c9296b;
  --line:rgba(255,255,255,.14);
  --panel:rgba(255,255,255,.045);
  --panel-2:rgba(255,255,255,.075);
  --ok:#7ee0b0;
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  min-height:100%;
  font-family:ui-rounded,'Hiragino Maru Gothic ProN',Quicksand,'Comic Sans MS',system-ui,sans-serif;
  color:var(--ink);
  background:linear-gradient(180deg,var(--bg3) 0%,var(--bg2) 45%,var(--bg1) 100%);
  /* :WHY? AN EXPLICIT background-color AFTER THE GRADIENT SHORTHAND, WHICH RESETS
     IT TO TRANSPARENT. A body that computes as transparent tells any injected
     fleet block that this page paints nothing, and the contact snippet's paint
     guard then hunts for the nearest painted element to borrow. On index.html it
     found a 3px amber dust mote and wore it as a card background. The longhand
     must stay AFTER the shorthand or the shorthand wipes it. */
  background-color:var(--bg1);
  background-attachment:fixed;
  overflow-x:hidden;
}

/* drifting fog, lifted from the landing so the two pages feel like one room */
.fog{position:fixed;inset:-20%;pointer-events:none;z-index:0;opacity:.5;
  background:radial-gradient(40% 30% at 30% 60%,rgba(90,120,200,.14),transparent 70%),
             radial-gradient(35% 25% at 75% 30%,rgba(120,90,200,.10),transparent 70%);
  animation:fogDrift 38s ease-in-out infinite alternate}
.fog.b{animation-duration:53s;animation-direction:alternate-reverse;opacity:.35;
  background:radial-gradient(45% 35% at 60% 70%,rgba(70,110,190,.12),transparent 70%)}
@keyframes fogDrift{from{transform:translate3d(-4%,-2%,0) scale(1)}to{transform:translate3d(4%,3%,0) scale(1.08)}}

/* ---------------------------------------------------------------- chrome -- */
header{position:sticky;top:0;z-index:20;display:flex;justify-content:space-between;
  align-items:center;gap:12px;padding:14px 20px;
  background:linear-gradient(180deg,rgba(4,6,11,.92),rgba(4,6,11,.55) 70%,transparent);
  backdrop-filter:blur(4px)}
.brand{font-weight:800;letter-spacing:.04em;font-size:15px;color:var(--pink-soft);text-decoration:none}
nav{display:flex;gap:16px;flex-wrap:wrap}
nav a{color:var(--dim);text-decoration:none;font-size:13.5px}
nav a:hover{color:var(--ink)}
nav a[aria-current="page"]{color:var(--pink);font-weight:700}

main{position:relative;z-index:1;max-width:860px;margin:0 auto;padding:18px 20px 90px}

.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

:focus-visible{outline:3px solid var(--pink-soft);outline-offset:2px;border-radius:6px}

h1{font-size:clamp(26px,5.4vw,40px);line-height:1.12;font-weight:800;
  text-shadow:0 0 34px rgba(255,95,162,.22)}
h1 em{font-style:normal;color:var(--pink)}
.lede{margin:12px 0 0;max-width:56ch;font-size:15px;line-height:1.75;color:var(--dim)}
.date-line{margin-top:6px;font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--dim)}

/* ------------------------------------------------------------ the bunny -- */
.bunny-wrap{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);gap:26px;
  align-items:center;margin:26px 0 6px}
@media (max-width:640px){.bunny-wrap{grid-template-columns:1fr;gap:14px}}

.stage{position:relative;width:100%;max-width:300px;margin:0 auto;aspect-ratio:1/1}
.halo{position:absolute;inset:-6%;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle at 50% 46%,rgba(255,95,162,.28),transparent 62%);
  opacity:calc(1 - var(--w,0) * .92);
  transition:opacity .9s ease}

svg.bun{width:100%;height:100%;overflow:visible;
  filter:drop-shadow(0 14px 20px rgba(0,0,0,.5))
         saturate(calc(1 - var(--w,0) * .78))
         brightness(calc(1 - var(--w,0) * .3));
  transition:filter 1s ease}
svg.bun *{transition:opacity .8s ease,transform .8s ease,fill .8s ease}
svg.bun .ears{transform-box:fill-box;transform-origin:50% 100%;
  transform:rotate(0deg) scaleY(calc(1 - var(--w,0) * .22))}
.bun .ear-l{transform-box:fill-box;transform-origin:50% 100%;
  transform:rotate(calc(var(--w,0) * -22deg))}
.bun .ear-r{transform-box:fill-box;transform-origin:50% 100%;
  transform:rotate(calc(var(--w,0) * 22deg))}
.bun .lid{transform-box:fill-box;transform-origin:50% 0;
  transform:scaleY(calc(var(--w,0) * .95))}
.bun .smile{opacity:calc(1 - var(--w,0) * 1.15)}
.bun .frown{opacity:calc(var(--w,0) * 1.1 - .25)}
.bun .cheek{opacity:calc(.85 - var(--w,0) * .85)}
.bun .sparkle{opacity:calc(1 - var(--w,0) * 3)}
.bun .haze{opacity:calc(var(--w,0) * .58)}
.bun .haze-2{opacity:calc(var(--w,0) * var(--w,0) * .6)}
.bun .tangle{opacity:0;stroke-dasharray:6 7}
.bun .tangle.on{opacity:.72}
.bun .gum{opacity:0;transform:scale(.4);transform-box:fill-box;transform-origin:50% 50%}
.bun .gum.on{opacity:.92;transform:scale(1)}
.bun .slump{transform-box:fill-box;transform-origin:50% 100%;
  transform:translateY(calc(var(--w,0) * 7px))}

.mood{margin-top:2px}
.mood .state-name{display:inline-block;font-size:19px;font-weight:800;color:var(--pink-soft)}
.mood .state-note{margin-top:8px;font-size:14.5px;line-height:1.7;color:var(--dim);max-width:42ch}

/* -------------------------------------------------------- the level bar -- */
.level{margin-top:8px;padding:16px 18px;border:1px solid var(--line);border-radius:16px;
  background:var(--panel)}
.level-top{display:flex;justify-content:space-between;align-items:baseline;gap:12px;flex-wrap:wrap}
.level-name{font-size:16px;font-weight:800;color:var(--pink)}
.level-count{font-size:13px;color:var(--dim);font-variant-numeric:tabular-nums}
.track{position:relative;height:14px;margin:12px 0 8px;border-radius:999px;
  background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.10);overflow:hidden}
.fill{height:100%;width:0%;border-radius:999px;
  background:linear-gradient(90deg,var(--pink-deep),var(--pink) 55%,var(--pink-soft));
  box-shadow:0 0 18px rgba(255,95,162,.5);
  transition:width .7s cubic-bezier(.22,1,.36,1)}
.ticks{display:flex;justify-content:space-between;gap:4px;list-style:none}
.ticks li{flex:1;font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
  color:rgba(232,236,245,.62);text-align:center;padding-top:2px;line-height:1.3}
.ticks li[data-reached="true"]{color:var(--pink-soft);font-weight:700}
@media (max-width:640px){.ticks li{font-size:9px}}

/* the level-up flourish: a burst of gum bubbles above the bar */
.pop-layer{position:relative;height:0}
.pop-bit{position:absolute;bottom:0;width:10px;height:10px;border-radius:50%;
  background:radial-gradient(circle at 32% 28%,#fff,var(--pink-soft) 45%,var(--pink) 100%);
  animation:popUp 1.15s cubic-bezier(.2,.7,.3,1) forwards;pointer-events:none}
@keyframes popUp{
  0%{transform:translate(0,0) scale(.3);opacity:0}
  18%{opacity:1}
  100%{transform:translate(var(--dx,0),-72px) scale(1.15);opacity:0}
}
.level.levelup{animation:levelGlow 1.1s ease}
@keyframes levelGlow{
  0%,100%{box-shadow:0 0 0 rgba(255,95,162,0)}
  40%{box-shadow:0 0 0 4px rgba(255,95,162,.28)}
}

/* ------------------------------------------------------- streak + strip -- */
.rows{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:14px;margin-top:16px}
.panel{padding:16px 18px;border:1px solid var(--line);border-radius:16px;background:var(--panel)}
.panel h2{font-size:14px;letter-spacing:.14em;text-transform:uppercase;color:var(--pink-soft);
  font-weight:800;margin-bottom:10px}
.streak-num{font-size:38px;font-weight:800;color:var(--pink);line-height:1;font-variant-numeric:tabular-nums}
.streak-sub{margin-top:6px;font-size:13.5px;color:var(--dim);line-height:1.6}
.info-btn{margin-top:10px;font:inherit;font-size:12.5px;color:var(--pink-soft);
  background:transparent;border:1px solid var(--line);border-radius:999px;
  padding:5px 12px;cursor:pointer}
.info-btn:hover{background:var(--panel-2)}
.info-note{margin-top:10px;padding:10px 12px;border-radius:10px;background:rgba(0,0,0,.35);
  border:1px solid var(--line);font-size:13px;line-height:1.65;color:var(--ink)}
.info-note[hidden]{display:none}

.strip{display:flex;gap:6px;flex-wrap:wrap;list-style:none;margin-top:4px}
.dot{width:20px;height:20px;border-radius:50%;border:2px solid rgba(255,255,255,.22);
  background:transparent;display:block}
.dot[data-kind="cleared"]{background:var(--pink);border-color:var(--pink);
  box-shadow:0 0 10px rgba(255,95,162,.55)}
.dot[data-kind="partial"]{border-color:var(--pink);background:rgba(255,95,162,.18)}
.dot[data-kind="empty"]{border-color:rgba(255,255,255,.22);background:rgba(255,255,255,.05)}
.strip li[data-today="true"] .dot{outline:2px solid var(--pink-soft);outline-offset:2px}
.strip-legend{margin-top:10px;font-size:12.5px;color:var(--dim);line-height:1.6}

/* ------------------------------------------------------------- the list -- */
.list-panel{margin-top:16px;padding:18px;border:1px solid var(--line);border-radius:18px;
  background:var(--panel)}
.list-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;
  margin-bottom:12px}
.list-head h2{font-size:14px;letter-spacing:.14em;text-transform:uppercase;color:var(--pink-soft);font-weight:800}

.adder{display:grid;grid-template-columns:auto 1fr auto auto;gap:8px;align-items:center}
@media (max-width:640px){.adder{grid-template-columns:auto 1fr;grid-auto-rows:auto}
  .adder .add-btn{grid-column:1 / -1}}
.field{font:inherit;font-size:15px;color:var(--ink);background:rgba(255,255,255,.07);
  border:1px solid var(--line);border-radius:12px;padding:11px 12px;min-width:0}
.field::placeholder{color:rgba(232,236,245,.55)}
.field:focus{border-color:var(--pink)}
select.field{padding:11px 8px;cursor:pointer}
select.field option{background:#0c1526;color:var(--ink)}
.tag-field{max-width:130px}
.add-btn{font:inherit;font-weight:800;font-size:15px;color:#fff;cursor:pointer;
  background:linear-gradient(180deg,var(--pink),var(--pink-deep));
  border:0;border-radius:999px;padding:11px 22px;box-shadow:0 6px 16px rgba(255,95,162,.35)}
.add-btn:hover{filter:brightness(1.08)}
.add-hint{margin-top:8px;font-size:12.5px;color:var(--dim)}

ul.todo{list-style:none;margin-top:16px;display:flex;flex-direction:column;gap:8px}
li.item{display:grid;grid-template-columns:auto auto 1fr auto;gap:10px;align-items:center;
  padding:10px 12px;border:1px solid var(--line);border-radius:14px;background:rgba(255,255,255,.05);
  transition:background .25s ease,border-color .25s ease,opacity .25s ease}
li.item:hover{border-color:rgba(255,95,162,.4)}
li.item.dragging{opacity:.45}
li.item.drop-target{border-color:var(--pink);background:rgba(255,95,162,.12)}
li.item.done{background:rgba(126,224,176,.08);border-color:rgba(126,224,176,.32)}
li.item.done .text-input{text-decoration:line-through;color:rgba(232,236,245,.66)}

.grip{cursor:grab;color:rgba(232,236,245,.55);font-size:15px;line-height:1;padding:4px 2px;
  background:transparent;border:0;user-select:none}
.grip:active{cursor:grabbing}
.check{width:22px;height:22px;accent-color:var(--pink);cursor:pointer;flex:none}
.mid{display:flex;align-items:center;gap:8px;min-width:0}
.emoji{font-size:18px;line-height:1;flex:none}
.text-input{flex:1;min-width:0;font:inherit;font-size:15.5px;color:var(--ink);
  background:transparent;border:1px solid transparent;border-radius:8px;padding:6px 8px}
.text-input:hover{border-color:var(--line)}
.text-input:focus{background:rgba(255,255,255,.08);border-color:var(--pink)}
.tag-chip{flex:none;font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--pink-soft);border:1px solid rgba(255,95,162,.4);border-radius:999px;
  padding:3px 9px;background:rgba(255,95,162,.12);white-space:nowrap;
  max-width:120px;overflow:hidden;text-overflow:ellipsis}
.tools{display:flex;gap:4px;flex:none}
.tool{font:inherit;font-size:13px;line-height:1;color:var(--dim);cursor:pointer;
  background:rgba(255,255,255,.06);border:1px solid var(--line);border-radius:9px;
  width:30px;height:30px;display:grid;place-items:center}
.tool:hover{color:var(--ink);background:var(--panel-2);border-color:rgba(255,95,162,.45)}
.tool[disabled]{opacity:.35;cursor:default}
.tool.del:hover{color:#ffc9dc;border-color:rgba(255,95,162,.7)}

.empty-note{margin-top:16px;padding:18px;border:1px dashed var(--line);border-radius:14px;
  text-align:center;font-size:14.5px;line-height:1.7;color:var(--dim)}
.empty-note strong{color:var(--pink-soft)}

.list-foot{display:flex;justify-content:space-between;align-items:center;gap:12px;
  flex-wrap:wrap;margin-top:14px;font-size:13px;color:var(--dim)}
.ghost-btn{font:inherit;font-size:13px;color:var(--dim);cursor:pointer;
  background:transparent;border:1px solid var(--line);border-radius:999px;padding:7px 14px}
.ghost-btn:hover{color:var(--ink);border-color:rgba(255,95,162,.5)}

footer.page{padding:34px 20px 20px;text-align:center;font-size:12.5px;color:var(--dim);line-height:1.8}
footer.page a{color:var(--pink-soft)}

/* --------------------------------------------------------- touch sizes -- */
/*
  :WHY? THIS KEYS OFF pointer:coarse, NOT A WIDTH BREAKPOINT. The thing that
  makes a 22px checkbox unusable is a fingertip, not a narrow window, and the two
  do not always travel together: a touch laptop has a wide viewport and a coarse
  pointer, while a narrow desktop window has neither. Sizing by width would grow
  the controls for someone dragging a window smaller and leave them tiny for
  someone actually tapping.

  :WHY? THE TOOL BUTTONS MOVE TO THEIR OWN ROW HERE. Three 44px buttons plus the
  checkbox and the grip do not leave a usable text field on a 375px screen, so
  the row wraps rather than squeezing the goal text down to a few characters.
*/
@media (pointer: coarse){
  li.item{grid-template-columns:auto auto 1fr;row-gap:8px}
  li.item .tools{grid-column:1 / -1;justify-content:flex-end;gap:8px}
  .tool{width:44px;height:44px;font-size:15px}
  .check{width:44px;height:44px}
  .grip{padding:12px 6px;font-size:18px}
  .text-input{padding:10px 8px}
  nav a{padding:12px 6px}
  .add-btn{padding:14px 24px}
  .ghost-btn,.info-btn{padding:12px 18px}
  .dot{width:24px;height:24px}
}

/* ----------------------------------------------------------- narrow rows -- */
/*
  :WHY? A GOAL ROW REFLOWS BELOW 520px INSTEAD OF SQUEEZING THE TEXT FIELD. The
  row is grip, checkbox, then emoji plus text plus tag chip, then three tool
  buttons, all on one line. Everything except the text has a fixed width, so the
  text field is the only thing that can absorb a narrow screen: at 375px with an
  emoji and a tag present it collapsed to around 18px, which is a field you
  cannot read your own goal in. The fix moves the furniture instead of the text.
  The tools drop to their own line and the emoji and tag chips wrap underneath
  the input, so the input keeps the whole width of the middle column, well over
  the 60 percent of the row it needs to stay usable.

  :WHY? A WIDTH QUERY, UNLIKE THE TOUCH SIZING ABOVE. Squeezing is caused by how
  much room there is, not by what is pointing at it, and a narrow desktop window
  with a mouse squeezes just as hard while never matching pointer:coarse. This
  block sits AFTER the coarse block on purpose, so where the two disagree the
  narrow rules win.

  :WHY? THE ORDER PROPERTY, RATHER THAN REORDERING THE MARKUP. The DOM order is
  emoji, text, tag, which is the order a screen reader should read and the order
  the tab sequence follows. Only the visual line breaks here, so order stays a
  presentation concern and the markup keeps meaning what it says.
*/
@media (max-width:520px){
  li.item{grid-template-columns:auto auto 1fr;gap:8px;padding:10px}
  li.item .tools{grid-column:1 / -1;justify-content:flex-end}
  .grip{padding:8px 2px;font-size:16px}
  .mid{flex-wrap:wrap;row-gap:6px}
  .mid .text-input{order:0;flex:1 1 100%}
  .mid .emoji{order:1}
  .mid .tag-chip{order:2;max-width:60%}
}

/* ------------------------------------------------------- reduced motion -- */
/* :WHY? THE LEVEL-UP FLOURISH IS THE ONE ANIMATION THAT CARRIES MEANING, so it
   is not simply deleted here. The bubbles and the bar glow stop, the width
   snaps instead of sliding, and the aria-live line still announces the new
   level. Nobody loses the information, only the movement. */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  .fog,.fog.b{animation:none}
  .fill{transition:none}
  .halo,svg.bun,svg.bun *{transition:none}
  .pop-bit{display:none}
  .level.levelup{animation:none;box-shadow:0 0 0 3px rgba(255,95,162,.4)}
  li.item{transition:none}
}
