/* Self-hosted so body text (Korean included) renders identically on every
   device instead of falling through each OS's own system-font stack —
   variable font, one file covers every weight the page uses via a plain
   `font-weight` value. SIL Open Font License — see
   static/fonts/pretendard/OFL.txt. */
@font-face {
  font-family: "Pretendard Variable";
  src: url("/static/fonts/pretendard/PretendardVariable.woff2") format("woff2");
  font-weight: 45 920;
  font-style: normal;
  font-display: swap;
}

body {
  /* Tailwind's own preflight is disabled (tailwind.config.js), and
     daisyUI's own reset never touches this — so the browser's default
     8px body margin was still live everywhere. Invisible on pages that
     already scroll, but on a single-screen layout sized to exactly match
     the viewport (guest_base.html's #guest-main, the no-scroll clock
     pages) that extra 16px (top+bottom) was just enough overflow to make
     the page scrollable by a few px, which shows up as a faint shift on
     swipe even though nothing was actually meant to move. */
  margin: 0;
  font-family: "Pretendard Variable", system-ui, -apple-system, "Apple SD Gothic Neo", "Malgun Gothic", sans-serif;
}

/* Self-hosted seven-segment display font for the "Segment" digital clock
   style (clock.html/worldclock.js/timezone-compare.js) — DSEG7-Classic
   deliberately includes each digit's unlit segments as a faint part of the
   glyph itself (the classic calculator/LCD look), which a regular
   monospace font has no way to reproduce. SIL Open Font License — see
   static/fonts/dseg7/OFL.txt. */
@font-face {
  font-family: "DSEG7 Classic";
  src: url("/static/fonts/dseg7/DSEG7Classic-Bold.woff2") format("woff2"),
       url("/static/fonts/dseg7/DSEG7Classic-Bold.woff") format("woff");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Opening either drawer used to shift <header>/<main> sideways, because
   daisyUI's own vendored rule changes the page's scroll state the moment
   one opens: `html:has(.drawer-toggle:checked){overflow-y:hidden;
   scrollbar-gutter:stable}`. Its intent is "hiding the page's real
   scrollbar to lock background scroll shouldn't shift the layout by the
   scrollbar's width" — but `scrollbar-gutter:stable` reserves that width
   *unconditionally*, so on a page with no scrollbar to begin with (most
   pages here, by design) the gutter appears out of nowhere on open and
   shifts everything left, then back on close.
   Reserving the gutter at all times instead did stop the shift, but left
   a permanently reserved strip at the right edge — invisible on a light
   theme, but a visibly different band on a dark one, which read as "a
   sliver of the drawer is showing".
   Neutralising daisyUI's state change entirely is what actually holds:
   nothing about the page changes when a drawer opens, so there is
   nothing to shift and nothing to reserve. The cost is that the page
   behind an open drawer stays scrollable — barely relevant here, where
   the pages deliberately don't scroll in the first place (see the
   no-scroll clock sizing entry in CLAUDE.md). */
html:has(.drawer-toggle:checked) {
  overflow-y: auto;
  scrollbar-gutter: auto;
}

/* daisyUI never actually *hides* a closed drawer: grep its vendored CSS
   and every `visibility` rule on .drawer-side sets `visible` (for the
   open state) — closed relies purely on translating the panel out by
   `translateX(±100%)`, i.e. exactly its own width. That leaves no margin
   for error, so anything that makes the panel paint past its translated
   box, or makes the translate land a hair short, shows up as a thin
   strip of the panel still at the screen edge with no menu content in
   it: subpixel rounding at fractional zoom/DPR, or a box-shadow (painted
   outside the border box, so translating the box away doesn't take the
   shadow with it).

   Rather than trying to compute how far short the translate lands (it
   depends on engine, OS scrollbar style and zoom, and measuring it from
   JS races the stylesheet actually being applied — both were tried and
   both failed), make "closed" mean genuinely invisible. The delayed
   transition keeps the slide-out animation: visibility only flips to
   hidden after daisyUI's own 0.3s transform transition has finished, and
   flips straight back to visible with no delay on open. */
.drawer-side {
  visibility: hidden;
  transition: visibility 0s linear 0.3s;
}

.drawer-toggle:checked ~ .drawer-side {
  visibility: visible;
  transition-delay: 0s;
}

/* The settings drawer's own panel is a fixed `w-96` (24rem/384px) and the
   nav menu's is `w-72` (18rem/288px) — on a narrower phone (under ~400px/
   300px CSS px respectively) that's wider than the screen itself. `.drawer-
   side`'s own box is already exactly viewport-width (daisyUI, `width:100%`,
   `position:fixed`), so capping the panel at 100% of that same box keeps it
   from overflowing past the real edge of the screen on any device, without
   touching daisyUI's own width on wider ones. */
#menu-drawer ~ .drawer-side > .menu,
#settings-drawer ~ .drawer-side > div {
  max-width: 100%;
}

/* Self-hosted so the site has no third-party font CDN dependency.
   SIL Open Font License — see static/fonts/righteous/OFL.txt. */
@font-face {
  font-family: "Righteous";
  src: url("/static/fonts/righteous/Righteous-Regular.woff2") format("woff2"),
       url("/static/fonts/righteous/Righteous-Regular.woff") format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* `100vh` on mobile Chrome/Samsung Internet is sized to the viewport with
   the address bar *hidden* (its largest possible size), even while the bar
   is actually showing and less is visible — so a flex-centered element
   inside a `100vh` box sits visibly below true screen-center until the
   user scrolls and the bar auto-hides, at which point the same box now
   matches the real viewport and the content visibly jumps to center. `dvh`
   tracks whichever amount is *actually* visible right now, so the content
   never needs to jump. Plain declarations first for browsers that don't
   know `dvh` (invalid value, so it's just skipped, leaving the `vh` one in
   effect) — every target browser here supports `dvh`, so the second line
   always wins where it's understood. */
.min-h-screen {
  min-height: 100vh;
  min-height: 100dvh;
}

/* `4rem`, not `3.5rem` — #guest-header is a plain daisyUI `.navbar`, whose
   own `min-height:4rem` is what actually sets its rendered height (the
   `3.5rem` this used before didn't match it, leaving a consistent 8px of
   extra page height below the fold — invisible as "being centered a
   little low", but just enough to make the page scroll that 8px on a
   swipe, which read as the whole page shifting). */
#guest-main {
  min-height: calc(100vh - 4rem);
  min-height: calc(100dvh - 4rem);
}

.logo-text {
  font-family: "Righteous", system-ui, sans-serif;
  letter-spacing: 0.01em;
}

/* Shared by #page-title and #clock-date so they're always the same size
   (per user request) — a `calc()` sum, not `clamp()`, specifically so the
   rem term keeps mattering at every container width: with clamp(1rem,
   1.1cqw, 2.4rem) the cqw term alone would decide the result whenever it
   landed between the two bounds, silently ignoring the "글자 크기"
   (font-size-sm/md/lg, which only rescale the rem term) setting outside
   fullscreen. Addition keeps both terms contributing everywhere: the rem
   term dominates in the normal, width-capped layout (so 글자 크기 is
   clearly felt), and the cqw term takes over as the container widens in
   fullscreen (mirroring how the clock digits also grow there) — both
   capped so it can't run away on a huge or ultrawide screen. */
.chrome-caption {
  font-size: min(calc(0.8rem + 1.1cqw), 2.4rem, 4.5vh);
}

/* /clock/world's #page-title/#wc-date are both pinned to the exact same
   64rem-based size /clock's own #page-title/#clock-date already get (both
   share .chrome-caption) — <main>/#wc-widget no longer widen past that
   64rem either (see main:has(#wc-widget) below, removed once the timeline
   moved to continent columns that fit inside it), so this formula is now
   an exact match rather than an approximation for a once-wider container.
   Kept as its own literal formula rather than relying on that now-equal
   width automatically, since #page-title still can't just
   get its own `container-type` to shrink its cqw basis — an element never
   containerizes *itself* for cq* units, only its descendants — so both
   reproduce what 1.1cqw evaluates to for /clock's own #page-title/#clock-
   date instead: for #page-title that's <main>'s real content-box, "min(64
   rem,96vw) minus <main>'s own 2rem of p-4 padding"; for
   #wc-date specifically (not #page-title) that's #clock-widget's real
   content-box — same formula *without* subtracting 2rem, since unlike
   <main>, neither #clock-widget nor #wc-header carries any horizontal
   padding of its own. Using the container-type approach below for #wc-date
   too (i.e. just capping #wc-header like #wc-time gets) lands about
   0.3px off from this at typical widths — #wc-header's own real content-
   box is the full capped 64rem with no padding to subtract, so its cqw
   comes out very slightly larger than what matching /clock's real
   (padded) #clock-date needs. Both skipped in fullscreen — there the whole
   point is filling the screen edge to edge, and #wc-header.clientWidth
   needs to reflect the *actual* fullscreen width for fitTimeFullscreen()'s
   own JS calculation, not a capped one. */
html:not(:fullscreen) main:has(#wc-widget) #page-title,
html:not(:fullscreen) #wc-date {
  font-size: min(calc(0.8rem + (min(64rem, 96vw) - 2rem) * 0.011), 2.4rem, 4.5vh);
}

/* /clock/world's "초기화" button used to live *inside* #page-title itself
   (worldclock.js appending it there at runtime, sharing the row with the
   big time's own city name) — chasing the position-jump bug that came from
   that (the button was inserted synchronously while the title text next to
   it only arrived later, async, so the row's own height — and the button's
   percentage-based vertical centering against it — changed out from under
   it) went through several rounds of increasingly narrow CSS/JS patches (a
   position:relative/position:absolute pairing here, then a min-height:1lh
   guard, then a JS-side placeholder character) that still didn't hold up in
   every browser. On request, all of it was deleted outright: the button is
   now plain server-rendered markup in its own grid column (world_clock.html's
   #wc-reset-btn, inside #wc-header's 3-column split below) that never
   shares a box with any async-updated text, so there is nothing left here
   to fix.

   #wc-time doesn't need the same pixel-exact cross-page matching #wc-date
   just got (there's no equivalent "big time" element on another page to
   match) — just a cap so it doesn't keep growing past 64rem on an
   ultra-wide screen while the cards below it still can. Capping the shared
   #wc-header parent handles the *width* directly. */
html:not(:fullscreen) #wc-header {
  width: 100%;
  max-width: 64rem;
  margin-inline: auto;
}

/* #wc-header-center (not #wc-header) is #wc-time's/#wc-date's own
   container-query basis now that #wc-header is split into 3 columns
   (world_clock.html, on request: "가로로 3등분해서 가운데 영역에 큰 시간을",
   originally 1fr/1fr/1fr, then re-ratioed to 1fr/8fr/1fr on a follow-up
   request — the left/right columns only ever need to fit the "초기화"
   button/stay empty, not a full third of the row) with the time/date
   living only in the center one — sizing their `cqw` terms off
   #wc-header's own (wider) box would let the digits' computed font-size
   overflow the actual column they render in. Unconditional (unlike
   #wc-header's width cap above, which stays fullscreen-exempt) since the
   column split itself isn't fullscreen-specific — #wc-header-center's own
   rendered width already reflects whichever mode is active (80% of the
   capped 64rem outside fullscreen, 80% of the wider uncapped row in
   fullscreen), so sizing off it directly gets both right with one rule. */
#wc-header-center {
  container-type: inline-size;
}

/* Digital faces only: #page-title's shared default margin-bottom
   (base.html, 0.75em) reads as too much space above the digital faces
   specifically — scoped via :has() to when a digital face is the one
   currently not [hidden], rather than lowering the shared default or
   scoping to the whole /clock page, so analog keeps the shared default
   untouched (its own gap was already tuned separately and needs no
   compensating override of its own this way). #page-title's
   margin-bottom is itself an inline style (base.html), which a plain
   stylesheet rule can't beat regardless of :has() specificity — hence
   !important here. */
main:has(.clock-face[data-face^="digital-"]:not([hidden])) #page-title {
  margin-bottom: 0.35em !important;
}

/* Same idea, same reason, for #clock-date's shared default margin-top
   (clock.html, 0.75em) — only tightened while a digital face is active. */
#clock-widget:has(.clock-face[data-face^="digital-"]:not([hidden])) #clock-date {
  margin-top: 0.35em !important;
}

/* Fullscreen digital faces are meant to look identical to /clock/world's
   own fullscreen big time (on request) — that page's #page-title
   margin-bottom and #wc-date margin-top are 0.75em (the untouched shared
   default) and 0.3em (world_clock.html's own inline value) respectively,
   neither of which is the 0.35em the two rules above use. `:fullscreen`
   raises specificity enough to win over those without needing source
   order, so this only takes effect in fullscreen — the normal-mode 0.35em
   (tuned separately, on its own earlier request) is untouched. */
:fullscreen main:has(.clock-face[data-face^="digital-"]:not([hidden])) #page-title,
:-webkit-full-screen main:has(.clock-face[data-face^="digital-"]:not([hidden])) #page-title {
  margin-bottom: 0.75em !important;
}

:fullscreen #clock-widget:has(.clock-face[data-face^="digital-"]:not([hidden])) #clock-date,
:-webkit-full-screen #clock-widget:has(.clock-face[data-face^="digital-"]:not([hidden])) #clock-date {
  margin-top: 0.3em !important;
}

/* ...and the face itself needs to fill the full fullscreen width the same
   way /clock/world's #wc-widget does (its width is never capped — main
   itself is widened instead, see main:has(#wc-widget) below), rather than
   staying capped at the normal-mode min(60rem,92vw) breakout size. Resets
   the breakout centering trick (margin-left:50%/translateX(-50%),
   clock.html) back to a plain, uncentered 100%-width block, since centering
   is no longer needed once the face is exactly as wide as its already-
   centered parent. Overrides inline styles, hence !important. */
:fullscreen .clock-face[data-face^="digital-"],
:-webkit-full-screen .clock-face[data-face^="digital-"] {
  width: 100% !important;
  margin-left: 0 !important;
  transform: none !important;
}

/* #wc-time (world_clock.html) sets line-height:1 itself; #normal-time/
   #segment-time/#wall-led-time don't set line-height at all, so they inherit
   the font stack's default (~1.5×) — normally invisible since it just
   pads the shared fixed-height face box a bit more, but in fullscreen
   fitDigital() reads this ratio to size the *box* the text must fit
   within, so the extra 0.5× was leaving a visibly bigger gap to the
   title/date than /clock/world's tight line-height:1 box does. None of
   the three has an inline line-height to fight, so this needs no
   !important. Scoped to fullscreen only — normal mode's line-height is
   its own separately-tuned thing and untouched here. */
:fullscreen #normal-time,
:fullscreen #segment-time,
:fullscreen #wall-led-time,
:-webkit-full-screen #normal-time,
:-webkit-full-screen #segment-time,
:-webkit-full-screen #wall-led-time {
  line-height: 1;
}

/* Same reasoning, one more component of the gap: the row wrapping each
   time div has its own vertical padding (clock.html,
   min(0.4cqw,0.3vh) top/bottom) — #wc-header has none at all. Zeroing
   just top/bottom (not the horizontal 3cqw, which doesn't affect
   position since the row centers its content either way) removes the
   last small offset between the two pages' fullscreen title-to-time and
   time-to-date gaps. Overrides an inline shorthand, hence !important. */
:fullscreen .clock-face[data-face^="digital-"] > div,
:-webkit-full-screen .clock-face[data-face^="digital-"] > div {
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* Root font-size scale for the "글자 크기" setting — Tailwind's rem-based
   utilities (text-6xl, gap-4, etc.) scale proportionally with this. */
html.font-size-sm {
  font-size: 87.5%;
}

html.font-size-md {
  font-size: 100%;
}

html.font-size-lg {
  font-size: 118%;
}

/* Some clock-face children set display:flex inline, which otherwise beats
   the UA stylesheet's [hidden] rule and leaves them visible. */
[hidden] {
  display: none !important;
}

/* "전체화면 모드" (settings.js requests fullscreen on <html>, so :fullscreen
   matches there — the rules below use it as an implicit ancestor). Hides
   the navbar and lets the page content fill and center in the viewport
   instead of sitting inside the normal max-w-5xl column. Vendor-prefixed
   duplicates are needed for WebKit, which doesn't recognize the unprefixed
   :fullscreen selector. */
:fullscreen header,
:-webkit-full-screen header,
:fullscreen #breadcrumb,
:-webkit-full-screen #breadcrumb {
  display: none;
}

/* Homepage (index.html doesn't override page_title, so the block renders
   empty there) would otherwise show a bare icon + "/" with nothing after
   it — :has() hides the whole row whenever its last child (the page-name
   span) has no text, rather than a template-side "is this the homepage"
   flag. */
#breadcrumb:has(span:last-child:empty) {
  display: none;
}

/* /clock/timezones: the breadcrumb already names the page, so the
   center-top "세계 시간 비교" heading is redundant there (on request) — but
   #page-title reuses the same {% block page_title %} the breadcrumb also
   renders, so the fix is scoped to this page's own #page-title instead of
   emptying that shared block, which would blank the breadcrumb label too. */
main:has(#tzc-widget) #page-title,
main:has(#alarm-widget) #page-title,
main:has(#countdown-widget) #page-title {
  display: none;
}

/* /clock/timezones in fullscreen: only the active view (cards or timeline)
   should show — no tabs or reset/date-time/view-toggle row (on request).
   #tzc-controls has its own inline `style="display:flex;..."` (templates/
   timezone_compare.html), which beats any plain selector regardless of
   specificity — same class of bug as the `:fullscreen #clock-widget{padding:0}`
   case (see the Clock faces entry above) — so this needs `!important` to
   actually win. */
:fullscreen #tzc-controls,
:-webkit-full-screen #tzc-controls {
  display: none !important;
}

/* The "추가" placeholder card/row (timezone-compare.js's makeAddCard()/
   makeAddTimelineRow()) used to stay visible in fullscreen alongside the
   rest of the view — on a follow-up request (after /alarm's own "추가" was
   hidden in fullscreen first), it's now hidden here too, so fullscreen
   shows just the time cards/timeline with none of the page's own controls.
   Both elements set their own inline `display:flex`/`display:grid` (see
   makeAddCard()/makeAddTimelineRow()), which silently no-opped a first
   version of this rule without `!important` — same class of bug as
   #tzc-controls above, caught when the "추가" card/row kept showing up in
   fullscreen despite this rule existing. */
:fullscreen .tzc-add-card,
:fullscreen .tzc-add-row,
:-webkit-full-screen .tzc-add-card,
:-webkit-full-screen .tzc-add-row {
  display: none !important;
}

/* /clock/timezones in fullscreen, card view: with the "추가" placeholder
   hidden above, a lone base card (no comparison cities added, on either
   tab) is the grid's only real child — CSS Grid still places a single item
   in the *first* track (top-left) by default rather than centering it, on
   request this should instead sit centered on the screen. #tzc-cards has
   its own inline `display:grid` (templates/timezone_compare.html), same
   !important gotcha as every other rule on this page's own inline styles.
   :not(:has(.tzc-compare-card)) is true exactly when no comparison city
   has been added — base and comparison cards otherwise share the same
   [data-city-id] attribute, so .tzc-compare-card (makeCard(), added to
   non-base cards only) is the one marker that distinguishes them. */
:fullscreen #tzc-cards:not(:has(.tzc-compare-card)),
:-webkit-full-screen #tzc-cards:not(:has(.tzc-compare-card)) {
  display: flex !important;
  justify-content: center;
}

:fullscreen #tzc-cards:not(:has(.tzc-compare-card)) > [data-role="base"],
:-webkit-full-screen #tzc-cards:not(:has(.tzc-compare-card)) > [data-role="base"] {
  width: 100%;
  /* 28rem matches /alarm's own solo-base-card width cap (below), for a
     consistent look across both pages — scaled by --tzc-card-scale too, so
     it can still grow along with everything else fitTzcScale() enlarges. */
  max-width: calc(28rem * var(--tzc-card-scale, 1));
}

/* /alarm in fullscreen: unlike /clock/timezones above, this page's own
   "추가" doesn't stay visible in fullscreen — on request, "초기화"/카드-
   타임라인 토글/"추가" should all disappear, leaving just the time cards/
   timeline. #alarm-controls has its own inline `style="display:flex;..."`
   (templates/alarm.html), same `!important`-needed gotcha as #tzc-controls
   above. */
:fullscreen #alarm-controls,
:-webkit-full-screen #alarm-controls {
  display: none !important;
}

/* .alarm-add-card/.alarm-add-row (alarm.js's makeAddCard()/
   makeAddTimelineRow()) also set their own inline `display:flex`/
   `display:grid`, the exact same gotcha as #alarm-controls just above —
   this rule did nothing without `!important` in an earlier pass, letting
   the empty card/"추가" button keep showing in fullscreen despite the rule
   existing. */
:fullscreen .alarm-add-card,
:fullscreen .alarm-add-row,
:-webkit-full-screen .alarm-add-card,
:-webkit-full-screen .alarm-add-row {
  display: none !important;
}

/* /alarm in fullscreen, card view: same reasoning as /clock/timezones'
   own solo-card rule above — with "추가" hidden, a lone base card (no
   alarms yet) is the grid's only real child, and on request it should sit
   centered on the screen instead of pinned to the grid's first (top-left)
   track. #alarm-cards has its own inline `display:grid` (templates/
   alarm.html), same !important gotcha as everything else on this page.
   :not(:has([data-alarm-id])) is true exactly when there are no alarms —
   unlike /clock/timezones, the base card here already has its own
   distinct [data-role="base"] (no shared attribute with alarm cards to
   disambiguate), so this needs no extra marker class. */
:fullscreen #alarm-cards:not(:has([data-alarm-id])),
:-webkit-full-screen #alarm-cards:not(:has([data-alarm-id])) {
  display: flex !important;
  justify-content: center;
}

:fullscreen #alarm-cards:not(:has([data-alarm-id])) > [data-role="base"],
:-webkit-full-screen #alarm-cards:not(:has([data-alarm-id])) > [data-role="base"] {
  width: 100%;
  max-width: calc(28rem * var(--alarm-card-scale, 1));
}

:fullscreen main,
:-webkit-full-screen main {
  max-width: none;
  width: 100vw;
  min-height: 100vh;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* #clock-widget's padding is an inline style (clock.html,
   padding-top/bottom:0.25rem), which a plain external rule can never
   override regardless of specificity — this rule had no effect at all
   until now (the same class of bug this file has hit before), leaving a
   stray 4px+4px gap in fullscreen that reservedChromeHeightPx() quietly
   compensated for in its height budget rather than actually zeroing out.
   Surfaced by comparing directly against /clock/world's fullscreen (whose
   #wc-widget carries no padding at all) — needs !important to actually
   apply. */
:fullscreen #clock-widget,
:-webkit-full-screen #clock-widget {
  padding: 0 !important;
}

/* Analog faces: the template's own inline width:80% is only the initial/
   no-JS value. clock.js's fitAnalog() overrides it with an explicit pixel
   width every tick, in and out of fullscreen — it needs to subtract the
   title/date's actual height first, to avoid forcing a scroll, and a pure
   CSS min(vw,vh)/percentage rule can't see that. No CSS override here on
   purpose: a stylesheet !important would always beat the plain inline
   style clock.js sets, which would make it un-resettable. */

/* Digital styles (segment/wall_led/normal): normally the time text just sits
   centered at a fixed proportion of its tile's width, so short formats
   (e.g. "8:41") leave a lot of empty margin on a wide fullscreen screen.
   clock.js's fitDigital handles this by growing the font-size (not
   spreading the characters apart — spread-out digits stop reading as one
   number), so no CSS is needed here either. */

/* World clock (/clock/world): normal mode no longer widens <main> past the
   site's shared max-w-5xl (64rem) — on request, the timeline should sit
   inside the same column the breadcrumb above it uses, not spill wider
   than it. This used to widen main (min(88rem,96vw)) first for the old
   bucket system's 7 columns, then for a flat wrap of up to 8 cards per
   continent row; both needed extra room a 64rem column didn't have. The
   current continent-columns layout (6 narrow columns of stacked city
   cards, worldclock.js's makeContinentSection/renderTimeline) fits inside
   64rem instead, so the widen override was removed rather than kept
   around unused. Fullscreen still gets its own horizontal breathing room
   below, independent of this. */

/* ...fullscreen still needs the shared :fullscreen main{max-width:none}
   (below) — nothing to win back over here now that the normal-mode widen
   above is gone, but the padding-inline:2rem this page still wants in
   fullscreen (see below) has to stay scoped to just this page. */
:fullscreen main:has(#wc-widget),
:-webkit-full-screen main:has(#wc-widget) {
  max-width: none;
  /* The shared :fullscreen main{padding:0} rule (below) reads fine for the
     big clock itself (its own text never reaches the viewport edges), but
     the timeline's city-card columns fill the full grid width and were
     landing flush against both edges with nothing to separate them from
     the screen — on request, give this page's own fullscreen a horizontal
     margin the shared rule doesn't have (vertical spacing above/below the
     widget is handled separately, via fitWidgetHeight()'s extra fullscreen
     reserve in worldclock.js). */
  padding-inline: 2rem;
}

/* On request: the "초기화" button (world_clock.html's #wc-reset-btn, in
   #wc-header's left column — see the 3-column split above) is hidden in
   fullscreen — this page's fullscreen view is meant to show just the big
   clock and the city-card timeline, the same reasoning :fullscreen header/
   #breadcrumb hiding above already follows for the rest of the page's own
   chrome. The button's own left/right sibling columns stay in the grid
   (an empty cell, same as the always-empty right column) so the big time
   in the center column doesn't shift — only the button itself disappears. */
:fullscreen #wc-reset-btn,
:-webkit-full-screen #wc-reset-btn {
  display: none;
}

/* World time comparison (/clock/timezones): unlike /clock and /clock/world's
   own intentional edge-to-edge fullscreen (this shared :fullscreen main rule
   is right for a single big clock face, but leaves this page's card grid
   touching the screen edges with nothing to visually separate them from it)
   — on request, restore the same 1rem edge padding <main> already has
   outside fullscreen (base.html's p-4) for this page specifically.
   :has(#tzc-widget) scopes it to just this page without touching the shared
   :fullscreen main rule or the other two pages' own fullscreen layouts. */
:fullscreen main:has(#tzc-widget),
:-webkit-full-screen main:has(#tzc-widget) {
  padding: 1rem;
}

/* Alarm clock (/alarm) in fullscreen: same edge-touching problem as
   /clock/timezones' own card grid above, but on request only the left/
   right edges need breathing room here (양 옆) — vertical spacing is
   already handled by the shared `:fullscreen main{justify-content:center}`
   centering the (possibly now bigger, via --alarm-card-scale) card grid/
   timeline within the viewport, so `padding-inline` alone is enough,
   matching /clock/world's own `padding-inline:2rem` fullscreen rule rather
   than /clock/timezones' full `padding:1rem` on every side. */
:fullscreen main:has(#alarm-widget),
:-webkit-full-screen main:has(#alarm-widget) {
  padding-inline: 2rem;
}

/* World clock (/clock/world): the big time used to be the only thing shown
   in fullscreen, growing to fill the whole screen with #wc-timeline-wrap
   hidden entirely — changed on request so both the clock and the small city
   cards below it stay visible together in fullscreen too, with only a
   modest size increase overall (see fitTimeFullscreen()/fitWidgetHeight() in
   worldclock.js: fitWidgetHeight() now sizes #wc-widget in fullscreen the
   same way it already does outside it, which is what lets #wc-timeline-wrap
   — flex:1, min-height:0, world_clock.html — actually claim the leftover
   vertical space instead of collapsing to 0; fitTimelineScale() then shrinks
   the timeline to fit whatever space is left, the same shrink-to-fit it
   already does outside fullscreen). No CSS override needed here any more —
   #wc-timeline-wrap's own inline display:flex (world_clock.html) is enough
   on its own now that nothing hides it. */

/* Two follow-up attempts at "the clock has too little/too much room around
   it in fullscreen" both ended up reverted — worth leaving a record so a
   future pass doesn't retry either:

   1. `:fullscreen #wc-timeline-wrap{flex:0 1 auto !important}` — stops the
      wrap (flex:1 1 auto normally, world_clock.html's own inline style)
      from growing past its natural content height, so the leftover space
      collects *outside* it instead of being split above/below the timeline
      by the wrap's own justify-content:center. This did close the gap
      between the clock and the cards, but also shrank it far more than
      outside fullscreen — normal mode never overrides this flex, so its
      wrap always grows and self-centers, and the clock-to-cards gap that
      produces is what the fullscreen layout is now meant to match (on
      request: "일반 모드일 때의 구성과 같은 비율로" — the same proportions as
      normal mode's own layout, not a tighter fullscreen-specific one).
      Removed — fullscreen now leaves the wrap's flex alone entirely, so it
      grows and centers exactly like normal mode, just scaled up into the
      taller fullscreen viewport.
   2. `:fullscreen #wc-widget{justify-content:center}` (paired with #1) —
      centered #wc-widget's *own* children (#wc-header + #wc-timeline-wrap)
      within its box, but #page-title (the "대한민국 · 서울 · UTC+9" line)
      lives *outside* #wc-widget, as its own sibling in <main> (base.html)
      — so #page-title stayed put while the header shifted away from it,
      visibly detaching the city name from its own clock. Also removed;
      `fitWidgetHeight()`'s own fullscreen reserve (worldclock.js) still
      gives `:fullscreen main{justify-content:center}` (below) slack to
      move #page-title and #wc-widget down *together* as one block, so
      that fix stays — the widget-level centering on top of it was the
      part that broke the title/clock relationship. */

/* #wc-time's 12-hour "오전"/"오후" (worldclock.js's formatBigTime, which
   wraps Intl's "dayPeriod" part in this span) — sized to match /clock's
   own digital faces, where the AM/PM badge is half the size of the time
   next to it in all three styles (7.5/22, 7.5/20, 7.5/18 — on request, the
   ratio was doubled project-wide from an earlier 1/4, since the badge read
   too small at 1/4 on /clock/timezones; the same doubled ratio was then
   applied here and on /alarm too, for consistency). `em` here means "half
   of whatever #wc-time's own font-size currently is", so this needs no JS
   recalculation when fitTimeFullscreen changes that size — it's just
   always relative to it. font-weight matches all three /clock styles too
   (700 in each).

   margin-inline is the gap to the digits next to it — /clock gets its own
   gap from a flex `gap:0.2em` on the *row* wrapping its ampm span/time div,
   which resolves against that row's own small inherited font-size (not the
   digits' huge one), landing at ~3.2px in practice. #wc-time has no such
   row (the ampm span is just inline text inside the same huge-font
   element), so `rem` here reproduces the same fixed, digit-size-
   independent ~3.2px directly (0.2rem = 3.2px at the default 16px root
   font-size) instead of an `em` that would scale with #wc-time's own huge
   size. formatBigTime (worldclock.js) drops the literal space Intl puts
   next to the dayPeriod part so this margin is the only gap, not an
   addition to it. */
.wc-ampm {
  font-size: 0.5em;
  font-weight: 700;
  margin-inline: 0.2rem;
}

/* text-shadow isn't an inherited property, so #wc-time's own segment/
   wall_led glow (applyBigTimeStyle, worldclock.js) wouldn't reach this
   nested span on its own — each needs the same treatment repeated here,
   plus the same per-style opacity /clock's own ampm badges use (0.7/0.75/
   0.85 — a deliberate, if minor, part of matching that page's exact
   look). wc-time-normal needs no rule: its ampm span already inherits the
   plain text color it needs. */
#wc-time.wc-time-normal .wc-ampm {
  opacity: 0.7;
}

#wc-time.wc-time-segment .wc-ampm {
  opacity: 0.75;
  color: #ffb000;
  text-shadow: 0 0 0.35em rgba(255, 176, 0, 0.75);
}

#wc-time.wc-time-wall_led .wc-ampm {
  opacity: 0.85;
  color: #ff2b2b;
  text-shadow: 0 0 0.3em rgba(255, 43, 43, 0.85);
}

/* The big clock's own sun/moon icon (formatBigTime, worldclock.js), on
   request — a nested inline span inside #wc-time, same reasoning as
   .wc-ampm above: `em` sizing means "relative to #wc-time's own current
   font-size" with no JS recalculation needed when fitTimeFullscreen()
   changes it. Color comes from the shared .tzc-daynight.tzc-day/.tzc-night
   rules below (the same ones the continent cards use), not repeated here —
   this class only adds the sizing/position those two rules don't carry. */
.wc-time-daynight {
  display: inline-block;
  width: 0.45em;
  height: 0.45em;
  vertical-align: middle;
  margin-inline-start: 0.15em;
}

/* /clock/timezones' and /alarm's shared AM/PM badge (formatCardTime,
   timezone-compare.js/alarm.js) — half the size of the digits it labels,
   same ratio as .wc-ampm above. Doubled from an original 1/4 on request
   ("'오전', '오후' 폰트 크기가 너무 작습니다" — the 1/4 ratio read as too
   small on this page specifically), then applied here and on /clock's own
   digital faces too so every page uses the same time:ampm ratio.
   margin-inline:0.2rem for the same reason as .wc-ampm: a literal space
   here would inherit the huge card font-size instead of staying a small,
   constant gap. */
.tzc-ampm {
  font-size: 0.5em;
  font-weight: 700;
  margin-inline: 0.2rem;
}

/* /clock/world's continent cards, /clock/timezones'/alarm's own timeline
   rows: on request ("'오전', '오후' 글자가 너무 작습니다"), the AM/PM badge
   is bumped to 1.5x the shared .tzc-ampm ratio above (0.5em → 0.75em) in
   just these three small-text contexts — .tzc-time (card view's own big
   time) is untouched, since this request was specifically about the
   smaller timeline/continent-card time displays, not the already-larger
   cards. Each selector's own higher specificity (two classes vs. one) wins
   over the shared default with no !important needed. */
.wc-continent-time .tzc-ampm,
.tzc-tl-time .tzc-ampm,
.alarm-tl-time .tzc-ampm {
  font-size: 0.75em;
}

/* Same non-inherited-properties reasoning as #wc-time.wc-time-<style>
   .wc-ampm above — only applied to .tzc-time (the card's big time), not
   .tzc-tl-time (the timeline row's small time), which never gets a
   tzc-time-<style> class since it stays plain-colored regardless of the
   selected digital style. */
.tzc-time.tzc-time-normal .tzc-ampm {
  opacity: 0.7;
}

.tzc-time.tzc-time-segment .tzc-ampm {
  opacity: 0.75;
  color: #ffb000;
  text-shadow: 0 0 0.35em rgba(255, 176, 0, 0.75);
}

.tzc-time.tzc-time-wall_led .tzc-ampm {
  opacity: 0.85;
  color: #ff2b2b;
  text-shadow: 0 0 0.3em rgba(255, 43, 43, 0.85);
}

/* The day/night icon (.tzc-daynight, shared by /clock/timezones and /alarm's
   card component) is a `stroke="currentColor"` SVG, so a plain `color` here
   is enough to tint it — sun in a warm amber, moon in a cool indigo, rather
   than both just inheriting the card's own muted text color. Not scoped to
   either page's widget id, same as the rest of this shared card CSS. */
.tzc-daynight.tzc-day {
  color: #f5a524;
}

.tzc-daynight.tzc-night {
  color: #6366f1;
}

/* ==== /timer ============================================================
   The breadcrumb already names the page (same shared {% block page_title %}
   reuse every other page's own #page-title hiding follows — see the
   Breadcrumb entry in CLAUDE.md), so the on-page copy is redundant here
   too, on the same reasoning as /alarm and /clock/timezones. */
main:has(#timer-widget) #page-title {
  display: none;
}

/* ---- Setup screen: the hour/minute/second "wheel" picker -------------- */
.timer-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding-inline: 0.5rem;
}

.timer-col-label {
  font-size: 0.9rem;
  font-weight: 600;
  opacity: 0.6;
}

.timer-col-row {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

/* Fixed-height 3-row "reel" — prev (dimmed) / current (bright) / next
   (dimmed) — showing a consecutive slice of the cyclic 0..max range
   (wrapping, e.g. hour 0's own "prev" reads 99), on request. touch-action:
   none stops a vertical swipe here from also scrolling the page itself,
   since timer.js's own pointermove handler is what should move the value
   instead. cursor:grab (grabbing while actively dragged, via the
   .timer-wheel-dragging class timer.js toggles) signals it's draggable
   without needing an extra visible affordance. */
.timer-wheel {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 3.4em;
  cursor: grab;
  touch-action: none;
  user-select: none;
}

.timer-wheel-dragging {
  cursor: grabbing;
}

.timer-wheel-value {
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
}

.timer-wheel-prev,
.timer-wheel-next {
  opacity: 0.3;
}

.timer-wheel-current {
  opacity: 1;
}

.timer-quick-btn {
  border-radius: 9999px;
}

/* Same gap above this grid (from the picker) as #timer-start-btn's own
   margin-top gives it below (to this grid) — on request, so the picker→
   quick-select and quick-select→start gaps read as equal, rather than the
   picker and quick-select sitting flush against each other. */
#timer-quick-select {
  margin-top: 2rem;
}

/* Bigger circular tap targets for 시작/취소/일시정지, matching the
   reference mockup's large round buttons rather than daisyUI's default
   btn-circle size. */
#timer-start-btn,
#timer-cancel-btn,
#timer-pause-btn {
  width: 6rem;
  height: 6rem;
  font-size: 1rem;
}

#timer-start-btn {
  margin-top: 2rem;
}

#timer-actions {
  gap: 3rem;
  margin-top: 2.5rem;
}

/* ---- Running screen: the radial-progress countdown face ---------------- */
/* --size is viewport-responsive (not JS-driven, unlike this project's other
   fullscreen-scaling pages) — capped at 22rem so it doesn't grow enormous
   on a huge display, and bounded by both vw/vh so a short *or* narrow
   viewport still leaves it fully on screen. Every child font-size below is
   expressed in `em` against this element's own font-size, itself a
   fraction of --size, so the whole face (label/time/bell row) scales as
   one unit purely via CSS, no resize listener needed. */
#timer-face {
  --value: 0;
  --size: min(70vw, 55vh, 22rem);
  --thickness: calc(var(--size) * 0.035);
  font-size: calc(var(--size) * 0.09);
  margin-top: 1.5rem;
}

/* Fullscreen: on request, the ring fills ~80% of whichever viewport
   dimension is tighter (not capped at 22rem like the normal-mode default
   above), leaving the other 20% as margin around it either way, and
   staying centered via the shared `:fullscreen main{justify-content:
   center}` rule now that #timer-actions is hidden and this is the only
   visible content left. Every font-size/--thickness inside is already a
   calc() off this same --size (see #timer-face/#timer-duration-label/
   #timer-time/#timer-fire-row above), so overriding just this one custom
   property scales the whole face — ring and every label/digit alike — by
   the same ratio, with no separate fullscreen font rule needed. The
   normal-mode margin-top is zeroed here too, or it would nudge the face
   slightly off true center. */
:fullscreen #timer-face,
:-webkit-full-screen #timer-face {
  --size: min(80vw, 80vh);
  margin-top: 0;
}

#timer-face-inner {
  text-align: center;
}

#timer-duration-label {
  font-size: 0.5em;
  font-weight: 600;
}

#timer-time {
  font-size: 1.7em;
  line-height: 1.1;
  margin-block: 0.15em;
}

#timer-fire-row {
  font-size: 0.5em;
  gap: 0.4em;
}

#timer-bell-icon {
  display: inline-flex;
  width: 1em;
  height: 1em;
}

/* Fullscreen: only the countdown itself stays on screen (on request) —
   #timer-controls/#timer-actions both set their own inline
   `style="display:flex;..."` (templates/timer.html), the same
   !important-needed gotcha as every other page's own fullscreen control-
   hiding rules (see the /alarm and /clock/timezones entries above). The
   shared `:fullscreen main{justify-content:center}` rule (below) is what
   actually centers the now-lone face on the screen — nothing page-specific
   needed for that part. */
:fullscreen #timer-controls,
:fullscreen #timer-actions,
:-webkit-full-screen #timer-controls,
:-webkit-full-screen #timer-actions {
  display: none !important;
}

/* ==== /stopwatch =========================================================
   Same reasoning as /timer's own entry above — the breadcrumb already
   names the page. */
main:has(#stopwatch-widget) #page-title {
  display: none;
}

/* Capped and centered, matching /timer's own narrow column — the laps
   list below reads better at a fixed readable width than stretched across
   the site's full 64rem main column. --stopwatch-scale (set by
   stopwatch.js's fitHeight(), one shared TIER_SCALE ratio for "작게"/
   "보통"/"크게") is what every font-size/gap below is expressed against,
   so the whole page — time, split line, lap table, buttons — grows or
   shrinks together as one unit instead of each element following its own
   incidental rem-based scaling. */
#stopwatch-widget {
  max-width: 28rem;
  margin-inline: auto;
}

/* #stopwatch-top has no explicit width of its own (align-items:center on
   #stopwatch-widget, its flex parent, otherwise lets it shrink-to-fit its
   content) — #stopwatch-laps-header lives inside it with width:100%, which
   against a shrink-to-fit ancestor resolves against whatever #stopwatch-top
   ends up sized to by its OTHER children (in practice #stopwatch-time's own
   rendered width, which changes with digit count/format/--stopwatch-scale).
   #stopwatch-laps (the lap rows' own container) is a separate sibling with
   width:100% of #stopwatch-widget itself (28rem, or narrower on a small
   screen) — a different reference width than #stopwatch-top's, so the
   header and the rows' grids ended up different total widths and their
   columns drifted apart, worse at some font-size tiers than others since
   the two reference widths scale differently. Pinning #stopwatch-top to
   the same 100%-of-widget width #stopwatch-laps already uses makes both
   grids share one reference width, so their (identical) grid-template-
   columns land at the same x-coordinates regardless of tier. */
#stopwatch-top {
  width: 100%;
}

#stopwatch-time {
  font-size: calc(4.5rem * var(--stopwatch-scale, 1) * var(--stopwatch-time-fit, 1));
  font-weight: 800;
  line-height: 1.1;
}

/* The "구간" (time-since-last-lap) line — hidden until the first lap, on
   request, at which point it appears right below the main time (which
   settles a bit higher purely as a consequence of new content taking its
   own place in this same centered flex column, no explicit animation
   needed) and starts counting from 0. Smaller and dimmer than the main
   time (opacity-50, on the element itself in stopwatch.html) so it reads
   as secondary at a glance. */
#stopwatch-split {
  font-size: calc(2rem * var(--stopwatch-scale, 1));
  font-weight: 700;
  margin-top: calc(0.3rem * var(--stopwatch-scale, 1));
}

#stopwatch-alert {
  margin-top: 1rem;
  max-width: 24rem;
}

/* 구간 / 구간 기록 / 전체 시간 — same 3-column grid as each lap row below,
   so headers and values line up. Only shown once a lap exists (see
   #stopwatch-split's own comment) — an empty table before that would just
   be visual clutter with nothing under it yet. */
#stopwatch-laps-header {
  display: grid;
  grid-template-columns: 1fr 1.4fr 1.4fr;
  gap: calc(0.5rem * var(--stopwatch-scale, 1));
  width: 100%;
  padding: calc(0.75rem * var(--stopwatch-scale, 1)) calc(0.75rem * var(--stopwatch-scale, 1)) calc(0.4rem * var(--stopwatch-scale, 1));
  font-size: calc(0.8rem * var(--stopwatch-scale, 1));
  font-weight: 600;
  opacity: 0.55;
  text-align: center;
  border-bottom: 1px solid color-mix(in oklch, var(--color-base-content) 15%, transparent);
}

/* The scrollable middle section — on request, once there are enough laps
   that the list would otherwise grow into #stopwatch-actions' own space,
   it scrolls internally instead (fitHeight() in stopwatch.js caps
   #stopwatch-widget's own height and this is the one flex child that
   absorbs the slack), newest lap prepended and the list kept scrolled to
   its own top so the newest is always immediately visible without the
   visitor needing to scroll up for it — older entries are still there,
   just reachable by scrolling/swiping down. */
#stopwatch-laps {
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
}

.stopwatch-lap-row {
  display: grid;
  grid-template-columns: 1fr 1.4fr 1.4fr;
  gap: calc(0.5rem * var(--stopwatch-scale, 1));
  padding: calc(0.5rem * var(--stopwatch-scale, 1)) calc(0.75rem * var(--stopwatch-scale, 1));
  text-align: center;
  font-size: calc(1rem * var(--stopwatch-scale, 1));
  border-bottom: 1px solid color-mix(in oklch, var(--color-base-content) 8%, transparent);
}

/* Shortest split → blue, longest → red (on request, literally those two
   colors) — daisyUI's info/error semantic colors, not "primary" (which
   /timer's own ring deliberately uses instead, precisely because it
   varies per theme — here the ask is the opposite: colors that read as
   recognizably blue/red regardless of theme, which info/error already
   are by daisyUI's own convention, the same way "warning" always reads
   yellow). Applies to all 3 cells of the row (구간/구간 기록/전체 시간)
   via `color` inherited by each plain-text cell — the two --tabular-nums
   cells (split/total) don't otherwise set their own `color` outside the
   segment/wall_led digital styles, which set an explicit inline color
   that still wins over this either way, same as everywhere else this
   TIME_STYLE pattern is used. */
.stopwatch-lap-best {
  color: var(--color-info);
}

.stopwatch-lap-worst {
  color: var(--color-error);
}

#stopwatch-actions {
  display: flex;
  gap: calc(3rem * var(--stopwatch-scale, 1));
  flex: 0 0 auto;
  margin-top: calc(1.5rem * var(--stopwatch-scale, 1));
  padding-block: calc(1rem * var(--stopwatch-scale, 1));
}

#stopwatch-lap-btn,
#stopwatch-toggle-btn {
  width: calc(6rem * var(--stopwatch-scale, 1));
  height: calc(6rem * var(--stopwatch-scale, 1));
  font-size: calc(1rem * var(--stopwatch-scale, 1));
}

/* In fullscreen, the shared `:fullscreen main{padding:0}` rule (this page
   has no page-specific override, unlike /clock/timezones'/#alarm's own)
   combined with header/breadcrumb collapsing to 0 height left fitHeight()'s
   own budget (window.innerHeight minus reservedChromeHeightPx(), which
   already reads <main>'s own computed padding) equal to the *entire*
   window height, so the widget's content ran edge to edge with nothing
   above/below it — on request, restore a bit of vertical breathing room.
   No JS change needed for this: reservedChromeHeightPx() re-reads <main>'s
   computed padding every time fitHeight() runs (already wired to the
   fullscreenchange event), so this plain CSS padding is picked up on its
   own the same way /clock/timezones'/#alarm's own fullscreen padding
   overrides already are. */
:fullscreen main:has(#stopwatch-widget),
:-webkit-full-screen main:has(#stopwatch-widget) {
  padding-block: 2rem;
}

/* /countdown. "도시 표시"/"날짜 표시" off hides the timezone/date cells with
   visibility (data-off, set by countdown.js) so the time keeps its grid cell. */
#countdown-widget [data-off] {
  visibility: hidden;
}

/* Too narrow for one "시간대 · 시간 · 날짜" line: stack the cells, and here
   collapse the hidden ones instead of leaving blank rows. */
@container (max-width: 34rem) {
  #countdown-widget {
    --cd-box-h: 14rem;
  }
  #countdown-widget .cd-info-row {
    grid-template-columns: 1fr !important;
    row-gap: 0.25rem;
  }
  #countdown-widget .cd-info-row > * {
    text-align: center !important;
  }
  #countdown-widget .cd-info-row > [data-off],
  #countdown-widget .cd-now-bottom > [data-off] {
    display: none;
  }
  #countdown-widget .cd-now-bottom {
    flex-direction: column;
    gap: 0.25rem;
    text-align: center;
  }
  #countdown-widget .cd-now-bottom > * {
    text-align: center !important;
  }
}

/* Fullscreen: only the countdown boxes, with side margins and a bit larger.
   The add box and the current-time card carry inline display styles or are
   plain blocks, so !important to be safe (see the /alarm rules above). */
:fullscreen #countdown-widget,
:-webkit-full-screen #countdown-widget {
  --cd-scale: 1.4;
}

:fullscreen main:has(#countdown-widget),
:-webkit-full-screen main:has(#countdown-widget) {
  padding-inline: 2rem;
}

:fullscreen #countdown-widget .cd-add-card,
:fullscreen #countdown-widget .cd-remove,
:-webkit-full-screen #countdown-widget .cd-add-card,
:-webkit-full-screen #countdown-widget .cd-remove {
  display: none !important;
}

/* The current-time card only hides once there are countdown boxes to show;
   with none, it is the one thing left in fullscreen. */
:fullscreen #countdown-widget:has(.cd-card) .cd-now-card,
:-webkit-full-screen #countdown-widget:has(.cd-card) .cd-now-card {
  display: none !important;
}

/* /shared-countdown/:id and /shared-countdown/join/:token: the single
   .cd-card these pages render reuses /countdown's own cd-* classes/CSS
   variables (BOX_HEIGHT, --cd-scale) for free — same "$id" widget-scoped
   [data-off]/fullscreen-scale rules, just scoped to these ids instead of
   #countdown-widget. No .cd-add-card/.cd-remove/.cd-now-card here (a room
   has neither an add box nor a "지금" card), so those hides don't apply.
   Hides the shared #page-title too — the breadcrumb already says "공유
   카운트다운", and #cdr-widget's own chrome/card say the room's own name,
   same reasoning room.html/shared_clock_room.html already hide it for. */
main:has(#cdr-widget) #page-title {
  display: none;
}

#cdr-widget [data-off],
#cdr-guest-widget [data-off] {
  visibility: hidden;
}
@container (max-width: 34rem) {
  #cdr-widget .cd-info-row,
  #cdr-guest-widget .cd-info-row {
    grid-template-columns: 1fr !important;
    row-gap: 0.25rem;
  }
  #cdr-widget .cd-info-row > *,
  #cdr-guest-widget .cd-info-row > * {
    text-align: center !important;
  }
  #cdr-widget .cd-info-row > [data-off],
  #cdr-guest-widget .cd-info-row > [data-off] {
    display: none;
  }
}
:fullscreen #cdr-widget,
:fullscreen #cdr-guest-widget,
:-webkit-full-screen #cdr-widget,
:-webkit-full-screen #cdr-guest-widget {
  --cd-scale: 1.4;
}
:fullscreen main:has(#cdr-widget),
:fullscreen main:has(#cdr-guest-widget),
:-webkit-full-screen main:has(#cdr-widget),
:-webkit-full-screen main:has(#cdr-guest-widget) {
  padding-inline: 2rem;
  align-items: center;
  justify-content: center;
}
/* #cdr-widget is itself a .card (room.html/shared_clock_room.html's own
   "everything in one big card" shape, on request) wrapping the single
   .cd-card its own JS renders — in fullscreen the outer card goes
   transparent/borderless so only the inner .cd-card's own background/
   shadow shows, rather than a card nested visibly inside another. */
:fullscreen #cdr-widget,
:-webkit-full-screen #cdr-widget {
  background: transparent;
  box-shadow: none;
  width: 100%;
}
:fullscreen #cdr-widget > .card-body,
:-webkit-full-screen #cdr-widget > .card-body {
  padding: 0;
  gap: 0;
}
:fullscreen .cdr-chrome,
:-webkit-full-screen .cdr-chrome {
  display: none !important;
}

/* daisyUI alerts get an "x" (static/js/alert-close.js). The button is
   positioned over the alert's right edge so it works whatever the alert's own
   grid content looks like; dismissing hides it until its page script changes it. */
.alert.alert-has-close {
  position: relative;
  padding-right: 3rem;
}
.alert-close {
  position: absolute;
  top: 50%;
  right: 0.5rem;
  transform: translateY(-50%);
  /* Every plain .btn plays a "button-pop" scale animation once on its own
     creation (daisyUI's `.btn{animation:button-pop .25s ease-out}`) — since
     the animation's keyframes set `transform`, it fights this button's own
     translateY(-50%) centering for that quarter-second, showing up as the
     button visibly settling into place right as the alert first appears.
     Not wanted here (this button isn't meant to draw attention on arrival),
     so it's disabled outright rather than just re-asserting the transform
     underneath it. */
  animation: none;
}
/* daisyUI's default .btn *press* animation (also button-pop, replaying on
   :active) has the same problem for the same reason, on every click rather
   than just on arrival — same fix. */
.alert-close:active:focus,
.alert-close:active:hover {
  animation: none;
  transform: translateY(-50%);
}
.alert[data-dismissed] {
  display: none !important;
}

/* Shared room page (/rooms/:id, /rooms/join/:token). The time follows the
   settings-drawer digital clock (format and style, room.js); in fullscreen
   only the title and the time remain, centered, with the time sized like
   /clock's (room.js fitTime). The card-relative size below is the normal-mode
   default before room.js shrinks it to fit. */
main:has(#room-card) #page-title {
  display: none;
}

#room-display {
  font-size: min(calc(1.6rem + 9cqw), 6rem);
}

:fullscreen main:has(#room-card),
:-webkit-full-screen main:has(#room-card) {
  padding-inline: 2rem;
  align-items: center;
  justify-content: center;
}

:fullscreen #room-card,
:-webkit-full-screen #room-card {
  background: transparent;
  box-shadow: none;
  width: 100%;
}

:fullscreen #room-card .card-body,
:-webkit-full-screen #room-card .card-body {
  padding: 0;
  gap: 0;
}

:fullscreen #room-card .room-chrome,
:-webkit-full-screen #room-card .room-chrome {
  display: none !important;
}

:fullscreen #room-title,
:-webkit-full-screen #room-title {
  font-size: min(calc(0.8rem + 1.1cqw), 2.4rem, 4.5vh);
  margin-bottom: 0.75em;
}

:fullscreen #room-display,
:-webkit-full-screen #room-display {
  line-height: 1;
}

/* /rooms: a room row and the dashed "add" row below the list share one height. */
.room-row,
.room-add-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  height: 3.5rem;
}
.room-add-row {
  justify-content: center;
  border: 2px dashed color-mix(in oklch, var(--color-base-content) 20%, transparent);
  background: var(--color-base-100);
}

/* /dashboard: same clickable-row look as .room-row, but each row can carry
   more columns (type badge, city, time, remaining) than a room list's own
   title+status — a fixed single-line height overflows narrow screens, so
   this wraps onto a second line there instead. */
.dash-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  row-gap: 0.25rem;
  min-height: 3.5rem;
  padding-block: 0.5rem;
}

/* .dash-row-active/.dash-row-empty need theme-reactive colors (a plain
   Tailwind bg-primary/10 doesn't work — daisyUI's colors aren't registered
   in tailwind.config.js, since daisyui.min.css is a separately vendored
   stylesheet rather than a Tailwind plugin), so these read the theme's own
   custom properties directly, same as .room-add-row's border above (daisyUI
   5's --color-* properties already come pre-wrapped in oklch(...), unlike
   v4's bare-triplet --b1/--bc/--p and their --fallback-* pairs, so opacity
   now goes through color-mix() instead of oklch(var(--x) / alpha)). An
   in-use row gets a light primary tint so it reads as "something's here";
   the "이용 중인 서비스가 없습니다" placeholder row instead matches the
   page's own background (not the card background) plus a dashed border, so
   it visibly recedes rather than looking like a real item. */
.dash-row-active {
  background: color-mix(in oklch, var(--color-primary) 8%, transparent);
}
.dash-row-active:hover {
  background: color-mix(in oklch, var(--color-primary) 16%, transparent);
}
.dash-row-empty {
  background: var(--color-base-200);
  border: 2px dashed color-mix(in oklch, var(--color-base-content) 15%, transparent);
}

/* /dashboard: the 피드백 history list has no fixed cap the way the timer/room
   sections above it do (any number of past submissions can exist), so
   instead of truncating it, the list itself scrolls within a height sized
   for about 5 rows — older entries are already in the DOM, just revealed by
   scrolling rather than a separate "load more" step. */
.dash-scroll-list {
  max-height: 20rem;
  overflow-y: auto;
}

/* /dashboard: the type/status pills ("카운트다운", "알람 시계", "공유 타이머",
   etc.) are filled with the theme's own primary color instead of daisyUI's
   flat .badge-outline — reads the theme's own --color-primary custom
   property (same reasoning as .dash-row-active/-empty above) so the fill
   still follows whatever theme is active; the text itself is plain white on
   request, not --color-primary-content (daisyUI's own auto-contrast
   pairing), which isn't always white depending on the theme. */
.dash-badge {
  border-color: transparent;
  background: var(--color-primary);
  color: #fff;
}

/* /rooms/new: labels sit to the left of their fields. */
.room-form-row {
  display: grid;
  grid-template-columns: 6rem minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}
.room-form-label {
  font-weight: 600;
  padding-top: 0.75rem;
}

/* ==== /shared-clock room view (templates/shared_clock_room.html) =========
   Reuses /clock/timezones' own .tzc-* class names on its cards (see
   shared-clock-room.js/shared-clock-create.js) for free styling — those
   rules aren't scoped to #tzc-widget, so nothing extra is needed for the
   time cards themselves. This block only covers what's specific to this
   page: hiding the shared #page-title (the outer #sc-header-row + card
   title already say the room name), and fullscreen — outside fullscreen
   nothing here needs the "sc-chrome" grouping since everything just shows.
*/
main:has(#shared-clock-card) #page-title {
  display: none;
}

:fullscreen #sc-header-row,
:fullscreen .sc-chrome,
:-webkit-full-screen #sc-header-row,
:-webkit-full-screen .sc-chrome {
  display: none !important;
}

:fullscreen main:has(#shared-clock-card),
:-webkit-full-screen main:has(#shared-clock-card) {
  padding: 1rem;
}

:fullscreen #shared-clock-card,
:-webkit-full-screen #shared-clock-card {
  background: transparent;
  box-shadow: none;
  width: 100%;
}

:fullscreen #shared-clock-card .card-body,
:-webkit-full-screen #shared-clock-card .card-body {
  padding: 0;
}

/* Every room-style page's "< 뒤로 가기" button (/rooms/new, /shared-clock/new,
   /shared-clock/:id, ...): daisyUI's .btn padding pushes its icon inward
   relative to plain content below it (the room-form-label / card content,
   which start flush at the container's own edge) — same class of
   misalignment the breadcrumb's home icon has against the hamburger button
   (see CLAUDE.md's Breadcrumb entry), fixed the same way: pull the icon
   back by the button's own padding so it lines up with the text below
   instead of sitting visibly indented from it. */
.room-back-btn {
  margin-left: -0.875rem;
}

/* Shared-room invite-link ("guest") pages: templates/guest_base.html and its
   two extenders (room_guest.html, shared_clock_guest.html). No settings
   drawer, no nav — just the logo/fullscreen header (hidden by the existing
   `:fullscreen header` rule above once real fullscreen is entered) and the
   content itself, styled to already look close to fullscreen by default
   since the real Fullscreen API can't be triggered without a click (see
   CLAUDE.md-adjacent design note in guest_base.html for why). */
#room-guest-widget,
#sc-guest-widget {
  width: 100%;
}

.guest-time-display {
  font-size: clamp(3rem, 18vw, 14rem);
}

@media (max-width: 640px) {
  #sc-guest-cards {
    grid-template-columns: minmax(0, 1fr) !important;
  }
}

/* Every `.btn-outline` on the site (the homepage's nav buttons, admin's
   pagination) is plain — no `btn-primary`/`btn-neutral`/etc. color modifier
   — so daisyUI 5 never gets a `--btn-color` to hover toward and falls back
   to tinting --color-base-200 (see its .btn:hover rule), which reads as a
   flat, theme-inconsistent gray instead of the button's own border color
   filling in. Filling with --color-base-content on hover (the same color
   the border/text already use at rest) and flipping the text to
   --color-base-100 reproduces the "outline fills with its own color, text
   turns light/dark for contrast" look daisyUI's colored outline buttons get
   for free — base-100 and base-content are always each theme's opposite
   extreme, so the pairing stays legible without per-theme tuning. */
.btn.btn-outline:hover {
  background-color: var(--color-base-content);
  color: var(--color-base-100);
}

/* /admin/feedback/:id/reply's Quill editor — by default `.ql-editor` just
   grows with its content (Quill only sets a `min-height`), so a long reply
   made the whole page scroll instead of the editor itself, on request.
   Fixing the height (not min-height) and scrolling internally keeps the
   toolbar/save button always on-screen regardless of reply length. */
#reply-editor-container .ql-editor {
  height: 50vh;
  min-height: 300px;
  overflow-y: auto;
}
