/* ==========================================================================
   เงินงอก office kit (NGERNNGOK-REDESIGN-PLAN.md, phase 1 Foundations).

   Direction G, "งานงอก Office": grid paper, boxed sheets, sticky notes, rubber
   stamps, folder tabs, highlighter bars, red-pen notes and a time card.

   Loaded last. Every token is --g- and every class is g-, so nothing here can
   reach a screen that has not moved over yet; phase 4 moves the screens one at
   a time. Light only for now (owner, 2026-10-16). Colours are tokens so a dark
   "กะดึก" theme can later redefine them without touching the parts.

   Fills and text are separate tokens on purpose. The bright pens (#E5322D,
   #1E8E46) are the mock-up's colours and are right for strokes, stamps' ink and
   icons, but read at only 3.7-3.8:1 as text on paper. Text uses the -text
   tokens, which tests/office-foundations.test.js holds at 4.5:1 on paper and
   on white.
   ========================================================================== */
:root {
  --g-paper: #f3f0e8;
  --g-grid: #e3ded2;
  --g-card: #ffffff;
  --g-ink: #1d2433;
  --g-ink-muted: #5b6170;
  --g-line: #1d2433;

  --g-note-yellow: #ffe45c;
  --g-note-pink: #ff9ec0;
  --g-note-blue: #9fd8ff;
  --g-note-green: #b6f08c;

  /* Pens: strokes, stamps, icons, the + button. */
  --g-pen-red: #e5322d;
  --g-pen-green: #1e8e46;
  --g-pen-blue: #2246d8;

  /* Pens as text. */
  --g-red-text: #c2261f;
  --g-money-text: #17723a;
  --g-blue-text: #2246d8;
  --g-gold-text: #8a5f0f;

  --g-lift: 0 3px 0 var(--g-ink);
  --g-note-shadow: 0 2px 0 rgba(29, 36, 51, 0.18);
  --g-radius: 14px;
  --g-radius-sm: 10px;
  --g-grid-size: 22px;

  --g-font-display: 'Kanit', 'IBM Plex Sans Thai Looped', system-ui, sans-serif;
  --g-font-body: 'Inter', 'IBM Plex Sans Thai Looped', system-ui, sans-serif;
  --g-font-hand: 'Sriracha', 'Kanit', cursive;
}

/* Grid paper: the ground every office screen sits on. */
.g-paper {
  background-color: var(--g-paper);
  background-image:
    linear-gradient(var(--g-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--g-grid) 1px, transparent 1px);
  background-size: var(--g-grid-size) var(--g-grid-size);
  color: var(--g-ink);
  font-family: var(--g-font-body);
}

.g-heading {
  margin: 0;
  font-family: var(--g-font-display);
  font-weight: 800;
  font-size: 24px;
  line-height: 1.25;
  color: var(--g-ink);
  text-wrap: balance;
}

/* Boxed sheet: the default container. Ink outline and a hard lift, never a
   blurred shadow, so it reads as paper on a desk. */
.g-sheet {
  background: var(--g-card);
  border: 1.5px solid var(--g-line);
  border-radius: var(--g-radius);
  box-shadow: var(--g-lift);
  padding: 14px 16px;
  color: var(--g-ink);
}

.g-sheet__title {
  margin: 0 0 6px;
  font-family: var(--g-font-display);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.3;
}

.g-muted {
  color: var(--g-ink-muted);
}

/* Sticky note. Tilt with --g-tilt; the tape strip is decoration only. */
.g-sticky {
  --g-note: var(--g-note-yellow);
  position: relative;
  background: var(--g-note);
  color: var(--g-ink);
  border-radius: 4px;
  padding: 14px 14px 12px;
  box-shadow: var(--g-note-shadow);
  transform: rotate(var(--g-tilt, -1.5deg));
}

.g-sticky::before {
  content: '';
  position: absolute;
  top: -8px;
  left: 50%;
  width: 54px;
  height: 16px;
  margin-left: -27px;
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid rgba(29, 36, 51, 0.08);
  transform: rotate(2deg);
}

.g-sticky--pink { --g-note: var(--g-note-pink); }
.g-sticky--blue { --g-note: var(--g-note-blue); }
.g-sticky--green { --g-note: var(--g-note-green); }

/* Rubber stamp: ด่วน in red, ผ่าน in green. Double ring like a real stamp. */
.g-stamp {
  display: inline-block;
  color: var(--g-red-text);
  border: 3px solid currentColor;
  border-radius: 8px;
  box-shadow: inset 0 0 0 2px var(--g-card), inset 0 0 0 3.5px currentColor;
  background: rgba(255, 255, 255, 0.7);
  padding: 2px 12px;
  font-family: var(--g-font-display);
  font-weight: 800;
  font-size: 15px;
  line-height: 1.3;
  letter-spacing: 0.04em;
  transform: rotate(var(--g-tilt, -8deg));
  white-space: nowrap;
}

.g-stamp--pass { color: var(--g-money-text); }

/* Add to a stamp the moment it is earned: it lands with a thunk. */
.g-stamp--thunk {
  animation: g-thunk 0.42s cubic-bezier(0.2, 0.9, 0.3, 1.25) both;
}

@keyframes g-thunk {
  0% { transform: rotate(var(--g-tilt, -8deg)) scale(1.9); opacity: 0; }
  60% { transform: rotate(var(--g-tilt, -8deg)) scale(0.94); opacity: 1; }
  100% { transform: rotate(var(--g-tilt, -8deg)) scale(1); opacity: 1; }
}

/* Folder tabs: a row of tabs on a ruled edge. The active tab joins the sheet
   below it. Use role="tablist" / role="tab" with aria-selected. */
.g-tabs {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1.5px solid var(--g-line);
  padding: 0 4px;
}

.g-tabs::-webkit-scrollbar { display: none; }

.g-tab {
  --g-tab-bg: var(--g-note-blue);
  flex-shrink: 0;
  min-height: 44px;
  margin-bottom: -1.5px;
  padding: 8px 14px 6px;
  border: 1.5px solid var(--g-line);
  border-bottom: 0;
  border-radius: 10px 10px 0 0;
  background: var(--g-tab-bg);
  color: var(--g-ink);
  font-family: var(--g-font-display);
  font-weight: 500;
  font-size: 14px;
  line-height: 1.2;
  cursor: pointer;
}

.g-tab[aria-selected="true"],
.g-tab.is-active {
  background: var(--g-card);
  padding-bottom: 12px;
  border-bottom: 1.5px solid var(--g-card);
  font-weight: 600;
}

.g-tab--yellow { --g-tab-bg: var(--g-note-yellow); }
.g-tab--pink { --g-tab-bg: var(--g-note-pink); }
.g-tab--green { --g-tab-bg: var(--g-note-green); }

/* Highlighter bar: a marker stroke over a pencil track. Set the value with
   style="--g-hl-value: 62%" and the colour with --g-hl-color. */
.g-highlight {
  --g-hl-value: 50%;
  --g-hl-color: var(--g-note-yellow);
  position: relative;
  height: 14px;
  border-radius: 3px;
  background: var(--g-grid);
}

.g-highlight::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: min(100%, var(--g-hl-value));
  background: var(--g-hl-color);
  border-radius: 3px 9px 4px 10px / 8px 3px 9px 4px;
  opacity: 0.92;
}

.g-highlight--over { --g-hl-color: var(--g-note-pink); }
.g-highlight--good { --g-hl-color: var(--g-note-green); }

/* Red-pen note: the handwritten voice of the cast. Short lines only. */
.g-pen-note {
  margin: 0;
  font-family: var(--g-font-hand);
  font-size: 17px;
  line-height: 1.45;
  color: var(--g-red-text);
}

.g-pen-note--blue { color: var(--g-blue-text); }

.g-pen-underline {
  text-decoration: underline wavy var(--g-pen-red);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 4px;
}

/* Time card: a week of days, punched when an entry was logged. */
.g-timecard {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
}

.g-timecard__day {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 40px;
  border: 1.5px dashed var(--g-ink-muted);
  border-radius: 6px;
  font-family: var(--g-font-display);
  font-weight: 600;
  font-size: 12px;
  color: var(--g-ink-muted);
}

.g-timecard__day.is-punched {
  border-style: solid;
  border-color: var(--g-line);
  background: var(--g-card);
  color: var(--g-ink);
}

.g-timecard__day.is-punched::after {
  content: '';
  position: absolute;
  width: 22px;
  height: 22px;
  border: 2.5px solid var(--g-pen-red);
  border-radius: 50%;
  opacity: 0.75;
}

.g-timecard__day.is-today {
  outline: 2px solid var(--g-pen-blue);
  outline-offset: 1px;
}

/* Amounts: Kanit with even digits so columns line up. */
.g-amount {
  font-family: var(--g-font-display);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--g-ink);
}

.g-amount--in { color: var(--g-money-text); }
.g-amount--out { color: var(--g-red-text); }

/* Buttons. Primary is ink, not a colour: the pens are for meaning. */
.g-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 18px;
  border: 1.5px solid var(--g-line);
  border-radius: var(--g-radius);
  background: var(--g-ink);
  color: var(--g-card);
  font-family: var(--g-font-display);
  font-weight: 600;
  font-size: 15px;
  cursor: pointer;
}

.g-btn--line {
  background: var(--g-card);
  color: var(--g-ink);
}

/* The round red + that logs an entry. Icon only, so it needs 3:1, not 4.5:1;
   the label goes in aria-label. */
.g-fab {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  border: 3px solid var(--g-line);
  border-radius: 50%;
  background: var(--g-pen-red);
  color: var(--g-card);
  box-shadow: var(--g-lift);
  cursor: pointer;
}

.g-btn:focus-visible,
.g-fab:focus-visible,
.g-tab:focus-visible {
  outline: 3px solid var(--g-pen-blue);
  outline-offset: 2px;
}

.g-btn:active,
.g-fab:active {
  transform: translateY(2px);
  box-shadow: 0 1px 0 var(--g-ink);
}

@media (prefers-reduced-motion: reduce) {
  .g-stamp--thunk { animation: none; }
  .g-btn:active,
  .g-fab:active { transform: none; }
}

/* --------------------------------------------------------------------------
   The name reveal on the boot cover (phase 2). The default timeline is the
   short drop; .g-reveal--full (added by js/name-reveal.js on first launch) is
   the long one. Every part sits inside the fixed cover, so nothing here moves
   the app underneath.
   -------------------------------------------------------------------------- */
#bootCover.g-reveal {
  background-color: var(--g-paper);
  background-image:
    linear-gradient(var(--g-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--g-grid) 1px, transparent 1px);
  background-size: var(--g-grid-size) var(--g-grid-size);
  color: var(--g-ink);
  overflow: hidden;
  gap: 18px;
}

.g-reveal__mark {
  display: flex;
  align-items: flex-end;
  font-family: var(--g-font-display);
  font-weight: 800;
  font-size: 76px;
  line-height: 1.15;
  color: var(--g-ink);
}

.g-reveal__front {
  position: relative;
  display: inline-block;
}

.g-reveal__gaan {
  position: absolute;
  right: 4px;
  bottom: 4px;
  font-weight: 500;
  font-size: 58px;
  color: #a9aeb8;
  transform-origin: 50% 100%;
  animation: g-gaan-out 0.55s cubic-bezier(0.4, 0, 0.8, 0.6) 0.33s both;
}

.g-reveal__ngern {
  display: inline-block;
  color: var(--g-money-text);
  transform-origin: 50% 100%;
  animation: g-ngern-drop 0.5s cubic-bezier(0.55, 0, 1, 0.6) 0.08s both;
}

.g-reveal__ngok {
  display: inline-block;
  transform-origin: 0 100%;
  animation: g-jolt 0.3s ease-out 0.35s both;
}

.g-reveal__puff {
  position: absolute;
  bottom: -4px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--g-grid);
  opacity: 0;
  animation: g-puff 0.4s ease-out 0.35s both;
}

.g-reveal__puff--left { --g-dx: -44px; left: 8px; }
.g-reveal__puff--right { --g-dx: 40px; right: 6px; width: 16px; height: 16px; }

.g-reveal__note,
.g-reveal__coin,
.g-reveal__tag {
  display: none;
}

/* Shown only if the ledger is still opening after the drop has landed. */
.g-reveal__bar {
  width: 132px;
  height: 3px;
  border-radius: 999px;
  background: var(--g-grid);
  overflow: hidden;
  opacity: 0;
  animation: g-fade-in 0.3s ease 1.2s forwards;
}

.g-reveal__bar span {
  display: block;
  width: 40%;
  height: 100%;
  border-radius: inherit;
  background: var(--g-ink);
  animation: g-sweep 1.1s ease-in-out infinite;
}

/* The long first-launch timeline: the work piles up first. */
.g-reveal--full .g-reveal__note {
  display: block;
  position: absolute;
  width: 108px;
  padding: 12px 10px;
  background: var(--g-note);
  box-shadow: 0 6px 12px rgba(29, 36, 51, 0.13);
  font-family: var(--g-font-hand);
  font-size: 16px;
  line-height: 1.3;
  color: var(--g-ink);
  animation:
    g-note-in 0.3s ease-out var(--g-d) both,
    g-note-out 0.55s ease-in 1.75s forwards;
}

.g-reveal__note--1 { --g-note: var(--g-note-yellow); --g-r: -8deg; --g-fx: -160px; --g-fy: -60px; --g-d: 0.1s; left: 12%; top: 12%; }
.g-reveal__note--2 { --g-note: var(--g-note-pink); --g-r: 6deg; --g-fx: 170px; --g-fy: -80px; --g-d: 0.3s; right: 8%; top: 15%; }
.g-reveal__note--3 { --g-note: var(--g-note-blue); --g-r: -3deg; --g-fx: -170px; --g-fy: 90px; --g-d: 0.5s; left: 14%; bottom: 22%; }
.g-reveal__note--4 { --g-note: var(--g-note-green); --g-r: 9deg; --g-fx: 160px; --g-fy: 110px; --g-d: 0.7s; right: 11%; bottom: 18%; }

.g-reveal--full .g-reveal__gaan { animation-delay: 1.65s; }
.g-reveal--full .g-reveal__ngern { --g-drop: -520px; animation-delay: 1.4s; }
.g-reveal--full .g-reveal__ngok,
.g-reveal--full .g-reveal__puff { animation-delay: 1.67s; }

.g-reveal--full .g-reveal__coin {
  display: block;
  position: absolute;
  width: 58px;
  height: 58px;
  animation: g-coin-in 0.4s cubic-bezier(0.2, 1.4, 0.4, 1) var(--g-d) both;
}

.g-reveal__coin--1 { --g-d: 2.2s; left: 18%; top: 14%; }
.g-reveal__coin--2 { --g-d: 2.3s; right: 15%; top: 17%; }
.g-reveal__coin--3 { --g-d: 2.4s; left: 24%; bottom: 24%; }
.g-reveal__coin--4 { --g-d: 2.5s; right: 14%; bottom: 20%; }

.g-reveal--full .g-reveal__tag {
  display: block;
  font-family: var(--g-font-hand);
  font-size: 21px;
  color: var(--g-blue-text);
  animation: g-tag-in 0.4s ease-out 2.5s both;
}

.g-reveal--full .g-reveal__bar { animation-delay: 3.7s; }

@keyframes g-ngern-drop {
  0% { transform: translateY(var(--g-drop, -280px)); }
  55% { transform: translateY(0) scale(1.14, 0.74); }
  72% { transform: translateY(-12px) scale(0.94, 1.08); }
  100% { transform: none; }
}

@keyframes g-gaan-out {
  0% { transform: none; opacity: 1; }
  15% { transform: translate(3px, 8px) rotate(8deg); opacity: 1; }
  100% { transform: translate(-30px, 420px) rotate(-80deg); opacity: 0; }
}

@keyframes g-jolt {
  0% { transform: none; }
  30% { transform: translateY(5px) rotate(-3deg); }
  70% { transform: translateY(-2px) rotate(1deg); }
  100% { transform: none; }
}

@keyframes g-puff {
  0% { transform: scale(0.2); opacity: 0; }
  20% { opacity: 0.9; }
  100% { transform: translate(var(--g-dx), -10px) scale(1.4); opacity: 0; }
}

@keyframes g-note-in {
  0% { transform: scale(0) rotate(var(--g-r)); opacity: 0; }
  70% { transform: scale(1.08) rotate(var(--g-r)); opacity: 1; }
  100% { transform: scale(1) rotate(var(--g-r)); opacity: 1; }
}

@keyframes g-note-out {
  0% { transform: scale(1) rotate(var(--g-r)); opacity: 1; }
  100% { transform: translate(var(--g-fx), var(--g-fy)) rotate(calc(var(--g-r) * 6)); opacity: 0; }
}

@keyframes g-coin-in {
  0% { transform: translateY(20px) scale(0); opacity: 0; }
  70% { transform: translateY(-6px) scale(1.1); opacity: 1; }
  100% { transform: none; opacity: 1; }
}

@keyframes g-tag-in {
  0% { transform: translateY(8px); opacity: 0; }
  100% { transform: none; opacity: 1; }
}

@keyframes g-fade-in {
  to { opacity: 1; }
}

@keyframes g-sweep {
  0% { transform: translateX(-110%); }
  100% { transform: translateX(360%); }
}

/* Reduced motion: the finished wordmark (and the tagline on first launch),
   nothing moving. js/name-reveal.js does not hold the cover in this case. */
@media (prefers-reduced-motion: reduce) {
  .g-reveal__gaan,
  .g-reveal__puff,
  .g-reveal--full .g-reveal__note,
  .g-reveal--full .g-reveal__coin { display: none; }
  .g-reveal__ngern,
  .g-reveal__ngok,
  .g-reveal--full .g-reveal__tag { animation: none; }
  .g-reveal__bar { animation: none; opacity: 1; }
  .g-reveal__bar span { animation: none; width: 100%; opacity: 0.45; }
}

/* --------------------------------------------------------------------------
   The cast (phase 3, js/cast.js). Decorative stickers beside messages that
   already say everything in words. Sized per place; never stretched.
   -------------------------------------------------------------------------- */
.g-cast {
  display: block;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

/* Midori noticed: a sticker in the tile corner, the text kept clear of it. */
.g-cast-host {
  position: relative;
  padding-right: 62px;
}

.g-cast--tile {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 54px;
  height: 54px;
}

.g-cast--head {
  display: inline-block;
  width: 28px;
  height: 28px;
  margin: -6px 2px -6px 0;
}

/* The toast is centred with left: 50%, which leaves shrink-to-fit only half
   the screen; with a sticker beside it, short Thai lines broke in two. */
#midoriToast:has(.g-cast--toast) {
  display: flex;
  align-items: center;
  gap: 10px;
  width: max-content;
}

.g-cast--toast {
  flex: none;
  width: 34px;
  height: 34px;
  margin: -8px 0;
}

.g-cast--dialog {
  width: 96px;
  height: 96px;
  margin: 0 auto 4px;
}

.g-cast--dialog[hidden] {
  display: none;
}
