/* App-specific custom CSS rules — Phase 6.5.5.
 *
 * Ported verbatim from the JS source `pwa-autofocus-app/src/App.css`,
 * minus rules that Tachyons already provides. These are the small set
 * of utilities and font hooks the JS port adds on top of Tachyons.
 *
 * Loaded by `resources/public/index.html` AFTER tachyons.min.css so that
 * any same-specificity collisions resolve in favor of these rules.
 */

/* Root reset — verbatim port of the JS port's index.css (Phase 7.12),
 * with one 12.5c divergence: `height: 100%` removed in favor of
 * `min-height` only.
 *
 * Three jobs:
 *   1. Zero margins on the root stack so the dark-theme background
 *      reaches every viewport edge.
 *   2. `display: flex; flex-direction: column` + `min-height: 100dvh`
 *      keep the root stack at least viewport-tall on every browser,
 *      including mobile where 100vh includes the URL bar.
 *   3. Font smoothing for sharper text on macOS/Chrome.
 *
 * Why drop `height: 100%`: with it, html/body/#app stayed pinned to
 * the viewport even when content overflowed, which constrained
 * <main> and `.app-container` to viewport height. The modal overlay
 * (absolute inside `.app-container`) then only extended as far as
 * the viewport, leaving overflow content uncovered. `min-height`
 * alone gives us the "fill viewport on short content" guarantee
 * without locking the root stack to that size when content is
 * taller. */
html, body, #app {
  margin: 0;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100%;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* Force form controls to use border-box (Phase 7.8). Tachyons sets
 * `* { box-sizing: inherit }` + `html { box-sizing: border-box }`,
 * but several browser user-agent stylesheets override that for
 * inputs/textareas with an explicit `box-sizing: content-box` — so
 * the `pa2` + `bw1` on `#new-todo` was adding ~20px to the visible
 * box and pushing the right edge past the buttons row's center axis.
 * Forcing border-box here fixes the new-todo input AND the
 * Import/Export modal textarea in one shot. */
input, textarea, select {
  box-sizing: border-box;
}

/* Montserrat hook — the Google Fonts `<link>` in index.html loads the
 * weights; this class opts an element into the family. Applied at the
 * <main> level so it cascades down. */
.montserrat {
  font-family: 'Montserrat', sans-serif;
}

/* Fixed 1.5rem height — status-icon span and per-row action buttons. */
.h-15 {
  height: 1.5rem;
}

/* Tight per-li line-height for the task list. */
.lh-135 {
  line-height: 1.35rem;
}

/* Subtle letter-spacing for the AutoFocus heading. */
.tracked-custom {
  letter-spacing: .05em;
}

/* Modern text-wrap balance — heading microtypography. */
.balance {
  text-wrap: balance;
}

/* Light-theme button background + hover/focus/active fade. */
.hover-bg-light-gray {
  background-color: rgba(238, 238, 238, 1);
  transition: all .2s ease-in;
}

.hover-bg-light-gray:hover,
.hover-bg-light-gray:focus {
  background-color: rgba(238, 238, 238, 0);
  transition: all .2s ease-in;
}

.hover-bg-light-gray:active {
  background-color: rgba(238, 238, 238, 0);
  transition: all .2s ease-out;
}

.active-bg-white:active {
  background-color: white;
}

.focus-bg-white:focus {
  background-color: white;
}

/* Dark-theme mirror — kept here for the future theme-toggle phase. */
.hover-bg-dark-gray {
  background-color: rgba(51, 51, 51, 1);
  transition: all .2s ease-in;
}

.hover-bg-dark-gray:hover,
.hover-bg-dark-gray:focus {
  background-color: rgba(51, 51, 51, 0);
  transition: all .2s ease-in;
}

.hover-bg-dark-gray:active {
  background-color: rgba(51, 51, 51, 0);
  transition: all .2s ease-out;
}

.active-bg-black:active {
  background-color: black;
}

.focus-bg-black:focus {
  background-color: black;
}

/* Modal-internal input variant — B-7 fix. The page-level new-todo
 * input uses `.hover-bg-light-gray` / `.hover-bg-dark-gray` directly:
 * those classes carry a `.2s ease-in` transition and fade the bg to
 * TRANSPARENT on hover/focus (revealing the page bg through).
 * Inside a modal that's wrong — the modal overlay is itself
 * translucent (`bg-white-90` / `bg-black-90`), so fading to
 * transparent stacks the translucency and washes the field out.
 *
 * Adding `.modal-input` alongside `.hover-bg-*-gray` keeps the rest
 * state (slightly gray in light, very dark gray in dark) AND the
 * smooth transition, but overrides the `:hover/:focus` end state to
 * solid white/black so the active field reads crisply. Specificity
 * (`.modal-input.hover-bg-*:hover` = 0,2,1) wins over the base rule
 * (`.hover-bg-*:hover` = 0,1,1).
 *
 * Visual contract: matches the new-todo input's rest appearance,
 * matches the OG ReactJS app's smooth `.2s` transition, ends on a
 * solid color (not transparent) so the field stays readable
 * against the modal overlay. */
.modal-input.hover-bg-light-gray:hover,
.modal-input.hover-bg-light-gray:focus {
  background-color: white;
}

.modal-input.hover-bg-dark-gray:hover,
.modal-input.hover-bg-dark-gray:focus {
  background-color: black;
}

/* On pointer-hover devices (desktop), per-row action buttons hide
 * until the row is hovered. On touch devices the @media block does not
 * match, so the buttons stay visible — that's the JS port's
 * progressive-enhancement strategy. */
@media (hover: hover) {
  .hover-button {
    display: none;
  }

  li:hover .hover-button {
    display: inline-block;
  }
}

/* Clamp a paragraph to 3 lines. Note: no `overflow: hidden` — matches
 * the JS port; pair with Tachyons' `overflow-hidden` at the call site
 * when you want truncation visible. */
.line-clamp-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

/* Convenience flex-grow shorthand. */
.flex-1 {
  flex: 1;
}

/* Add `mb1` (0.25rem) to every `<li>` except the last in the same parent. */
.mb1-butlast:not(:last-child) {
  margin-bottom: 0.25rem;
}

/* Long unbroken strings wrap inside their container instead of forcing
 * horizontal scroll. Applied to the per-row task text span. */
.break-word {
  word-break: break-word;
  overflow-wrap: break-word;
}

/* Zero-height utility — used to collapse a visually-hidden region
 * while leaving it in the accessibility tree. */
.h0 {
  height: 0;
}

/* Phase 19o — skip link for keyboard users.
 *
 * Hidden off-screen by default; becomes visible (and a high-contrast
 * focusable target) when Tab-focused. Pressing Enter sends focus to
 * the `#main-content` section, letting keyboard users bypass the
 * header icon buttons. WCAG 2.1 success criterion 2.4.1 (Bypass
 * Blocks). Mouse users never see it.
 *
 * `position: fixed` + `top: -100px` is the cross-browser standard
 * for "visually hidden but in the accessibility tree" — older
 * `display: none` removes it from AT, `clip` plus a fade is
 * unreliable across UAs. The `:focus` override scrolls it into view
 * at the top-left of the viewport. */
.skip-link {
  position: fixed;
  top: -100px;
  left: 0.5rem;
  background: white;
  color: black;
  padding: 0.5rem 1rem;
  border: 2px solid black;
  border-radius: 0.25rem;
  font-weight: 600;
  text-decoration: none;
  z-index: 1000;
}

.skip-link:focus {
  top: 0.5rem;
  outline: 3px solid #0066cc;
  outline-offset: 2px;
}

/* Dark-theme variant. The body class flips via
 * `learn.client.lifecycle/sync-body-theme-class!` so we can target
 * `body.bg-black .skip-link` for the dark-mode look. Without this,
 * the white background on the skip link clashes badly with the
 * dark theme. */
body.bg-black .skip-link {
  background: black;
  color: white;
  border-color: white;
}

/* Phase 19p a11y — respect `prefers-reduced-motion`.
 *
 * WCAG 2.3.3 (Animation from Interactions) recommends disabling
 * non-essential animations when the user has expressed a reduced-
 * motion preference at the OS level (Windows: Settings → Ease of
 * Access → Display → Show animations; macOS: System Prefs →
 * Accessibility → Display → Reduce motion; Linux: varies by DE).
 *
 * Our only transitions are the 0.2s button background fades
 * (`.hover-bg-light-gray`, `.hover-bg-dark-gray`, `.modal-input`
 * variants). They're purely decorative — the visual state is
 * equally communicated by the rest/hover/focus background change
 * itself. Setting `transition: none !important` keeps the end
 * state but skips the animation.
 *
 * `animation: none` is included for future-proofing — we don't
 * use CSS keyframes today, but if we add any, this guard will
 * cover them too without a separate change. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
