/* GENERATED by bin/build — do not edit. Edit src/tailwind.appdev.css instead. */
/* ================================================
   TAILWIND.APPDEV.CSS

   A drop-in replacement for the Pico CSS stack:
   named components + classless styling for semantic
   HTML, built on Tailwind's default design tokens.

   Sources live in src/: this stylesheet plus a
   generated tailwind.theme.css (Tailwind's full
   default theme as CSS variables). bin/build bakes
   the theme in where the @import sits, producing
   the single-file artifact at the repo root — the
   file apps actually link.

   Meant to be used alongside the Tailwind browser
   build (which supplies Preflight + utility classes):

     <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.3"></script>
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/firstdraft/tailwind.appdev.css@latest/tailwind.appdev.css">

   The theme variables are required: the browser build
   tree-shakes its theme, emitting only the variables
   its utility classes actually use, so without them
   every var() below resolves to nothing. (They play
   the role bootstrap-utilities.css played in the old
   stack, supplying the --bs-* variables that
   pico.firstdraft.css consumed.)

   GATING: nothing here applies until you add
   class="appdev-styles" to your <body> — just like Pico's
   conditional stylesheet needed class="pico". Without
   it, pages get Tailwind's Preflight and utility
   classes only.

   Everything lives in the `components` cascade layer
   so that Tailwind utility classes in your HTML
   always win over these defaults.
=================================================== */

@layer theme, base, components, utilities;

/* Tailwind's full default theme as CSS variables. In this source file it is
   a separate generated file pulled in via @import (a @layer statement is the
   one kind of rule the CSS spec allows before @import); bin/build replaces
   this line with the file's contents to produce the single-file artifact. */
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
:root, :host {
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 'Noto Sans', Arial,
    sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
  --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
    monospace;
  --color-red-50: oklch(97.1% 0.013 17.38);
  --color-red-100: oklch(93.6% 0.032 17.717);
  --color-red-200: oklch(88.5% 0.062 18.334);
  --color-red-300: oklch(80.8% 0.114 19.571);
  --color-red-400: oklch(70.4% 0.191 22.216);
  --color-red-500: oklch(63.7% 0.237 25.331);
  --color-red-600: oklch(57.7% 0.245 27.325);
  --color-red-700: oklch(50.5% 0.213 27.518);
  --color-red-800: oklch(44.4% 0.177 26.899);
  --color-red-900: oklch(39.6% 0.141 25.723);
  --color-red-950: oklch(25.8% 0.092 26.042);
  --color-orange-50: oklch(98% 0.016 73.684);
  --color-orange-100: oklch(95.4% 0.038 75.164);
  --color-orange-200: oklch(90.1% 0.076 70.697);
  --color-orange-300: oklch(83.7% 0.128 66.29);
  --color-orange-400: oklch(75% 0.183 55.934);
  --color-orange-500: oklch(70.5% 0.213 47.604);
  --color-orange-600: oklch(64.6% 0.222 41.116);
  --color-orange-700: oklch(55.3% 0.195 38.402);
  --color-orange-800: oklch(47% 0.157 37.304);
  --color-orange-900: oklch(40.8% 0.123 38.172);
  --color-orange-950: oklch(26.6% 0.079 36.259);
  --color-amber-50: oklch(98.7% 0.022 95.277);
  --color-amber-100: oklch(96.2% 0.059 95.617);
  --color-amber-200: oklch(92.4% 0.12 95.746);
  --color-amber-300: oklch(87.9% 0.169 91.605);
  --color-amber-400: oklch(82.8% 0.189 84.429);
  --color-amber-500: oklch(76.9% 0.188 70.08);
  --color-amber-600: oklch(66.6% 0.179 58.318);
  --color-amber-700: oklch(55.5% 0.163 48.998);
  --color-amber-800: oklch(47.3% 0.137 46.201);
  --color-amber-900: oklch(41.4% 0.112 45.904);
  --color-amber-950: oklch(27.9% 0.077 45.635);
  --color-yellow-50: oklch(98.7% 0.026 102.212);
  --color-yellow-100: oklch(97.3% 0.071 103.193);
  --color-yellow-200: oklch(94.5% 0.129 101.54);
  --color-yellow-300: oklch(90.5% 0.182 98.111);
  --color-yellow-400: oklch(85.2% 0.199 91.936);
  --color-yellow-500: oklch(79.5% 0.184 86.047);
  --color-yellow-600: oklch(68.1% 0.162 75.834);
  --color-yellow-700: oklch(55.4% 0.135 66.442);
  --color-yellow-800: oklch(47.6% 0.114 61.907);
  --color-yellow-900: oklch(42.1% 0.095 57.708);
  --color-yellow-950: oklch(28.6% 0.066 53.813);
  --color-lime-50: oklch(98.6% 0.031 120.757);
  --color-lime-100: oklch(96.7% 0.067 122.328);
  --color-lime-200: oklch(93.8% 0.127 124.321);
  --color-lime-300: oklch(89.7% 0.196 126.665);
  --color-lime-400: oklch(84.1% 0.238 128.85);
  --color-lime-500: oklch(76.8% 0.233 130.85);
  --color-lime-600: oklch(64.8% 0.2 131.684);
  --color-lime-700: oklch(53.2% 0.157 131.589);
  --color-lime-800: oklch(45.3% 0.124 130.933);
  --color-lime-900: oklch(40.5% 0.101 131.063);
  --color-lime-950: oklch(27.4% 0.072 132.109);
  --color-green-50: oklch(98.2% 0.018 155.826);
  --color-green-100: oklch(96.2% 0.044 156.743);
  --color-green-200: oklch(92.5% 0.084 155.995);
  --color-green-300: oklch(87.1% 0.15 154.449);
  --color-green-400: oklch(79.2% 0.209 151.711);
  --color-green-500: oklch(72.3% 0.219 149.579);
  --color-green-600: oklch(62.7% 0.194 149.214);
  --color-green-700: oklch(52.7% 0.154 150.069);
  --color-green-800: oklch(44.8% 0.119 151.328);
  --color-green-900: oklch(39.3% 0.095 152.535);
  --color-green-950: oklch(26.6% 0.065 152.934);
  --color-emerald-50: oklch(97.9% 0.021 166.113);
  --color-emerald-100: oklch(95% 0.052 163.051);
  --color-emerald-200: oklch(90.5% 0.093 164.15);
  --color-emerald-300: oklch(84.5% 0.143 164.978);
  --color-emerald-400: oklch(76.5% 0.177 163.223);
  --color-emerald-500: oklch(69.6% 0.17 162.48);
  --color-emerald-600: oklch(59.6% 0.145 163.225);
  --color-emerald-700: oklch(50.8% 0.118 165.612);
  --color-emerald-800: oklch(43.2% 0.095 166.913);
  --color-emerald-900: oklch(37.8% 0.077 168.94);
  --color-emerald-950: oklch(26.2% 0.051 172.552);
  --color-teal-50: oklch(98.4% 0.014 180.72);
  --color-teal-100: oklch(95.3% 0.051 180.801);
  --color-teal-200: oklch(91% 0.096 180.426);
  --color-teal-300: oklch(85.5% 0.138 181.071);
  --color-teal-400: oklch(77.7% 0.152 181.912);
  --color-teal-500: oklch(70.4% 0.14 182.503);
  --color-teal-600: oklch(60% 0.118 184.704);
  --color-teal-700: oklch(51.1% 0.096 186.391);
  --color-teal-800: oklch(43.7% 0.078 188.216);
  --color-teal-900: oklch(38.6% 0.063 188.416);
  --color-teal-950: oklch(27.7% 0.046 192.524);
  --color-cyan-50: oklch(98.4% 0.019 200.873);
  --color-cyan-100: oklch(95.6% 0.045 203.388);
  --color-cyan-200: oklch(91.7% 0.08 205.041);
  --color-cyan-300: oklch(86.5% 0.127 207.078);
  --color-cyan-400: oklch(78.9% 0.154 211.53);
  --color-cyan-500: oklch(71.5% 0.143 215.221);
  --color-cyan-600: oklch(60.9% 0.126 221.723);
  --color-cyan-700: oklch(52% 0.105 223.128);
  --color-cyan-800: oklch(45% 0.085 224.283);
  --color-cyan-900: oklch(39.8% 0.07 227.392);
  --color-cyan-950: oklch(30.2% 0.056 229.695);
  --color-sky-50: oklch(97.7% 0.013 236.62);
  --color-sky-100: oklch(95.1% 0.026 236.824);
  --color-sky-200: oklch(90.1% 0.058 230.902);
  --color-sky-300: oklch(82.8% 0.111 230.318);
  --color-sky-400: oklch(74.6% 0.16 232.661);
  --color-sky-500: oklch(68.5% 0.169 237.323);
  --color-sky-600: oklch(58.8% 0.158 241.966);
  --color-sky-700: oklch(50% 0.134 242.749);
  --color-sky-800: oklch(44.3% 0.11 240.79);
  --color-sky-900: oklch(39.1% 0.09 240.876);
  --color-sky-950: oklch(29.3% 0.066 243.157);
  --color-blue-50: oklch(97% 0.014 254.604);
  --color-blue-100: oklch(93.2% 0.032 255.585);
  --color-blue-200: oklch(88.2% 0.059 254.128);
  --color-blue-300: oklch(80.9% 0.105 251.813);
  --color-blue-400: oklch(70.7% 0.165 254.624);
  --color-blue-500: oklch(62.3% 0.214 259.815);
  --color-blue-600: oklch(54.6% 0.245 262.881);
  --color-blue-700: oklch(48.8% 0.243 264.376);
  --color-blue-800: oklch(42.4% 0.199 265.638);
  --color-blue-900: oklch(37.9% 0.146 265.522);
  --color-blue-950: oklch(28.2% 0.091 267.935);
  --color-indigo-50: oklch(96.2% 0.018 272.314);
  --color-indigo-100: oklch(93% 0.034 272.788);
  --color-indigo-200: oklch(87% 0.065 274.039);
  --color-indigo-300: oklch(78.5% 0.115 274.713);
  --color-indigo-400: oklch(67.3% 0.182 276.935);
  --color-indigo-500: oklch(58.5% 0.233 277.117);
  --color-indigo-600: oklch(51.1% 0.262 276.966);
  --color-indigo-700: oklch(45.7% 0.24 277.023);
  --color-indigo-800: oklch(39.8% 0.195 277.366);
  --color-indigo-900: oklch(35.9% 0.144 278.697);
  --color-indigo-950: oklch(25.7% 0.09 281.288);
  --color-violet-50: oklch(96.9% 0.016 293.756);
  --color-violet-100: oklch(94.3% 0.029 294.588);
  --color-violet-200: oklch(89.4% 0.057 293.283);
  --color-violet-300: oklch(81.1% 0.111 293.571);
  --color-violet-400: oklch(70.2% 0.183 293.541);
  --color-violet-500: oklch(60.6% 0.25 292.717);
  --color-violet-600: oklch(54.1% 0.281 293.009);
  --color-violet-700: oklch(49.1% 0.27 292.581);
  --color-violet-800: oklch(43.2% 0.232 292.759);
  --color-violet-900: oklch(38% 0.189 293.745);
  --color-violet-950: oklch(28.3% 0.141 291.089);
  --color-purple-50: oklch(97.7% 0.014 308.299);
  --color-purple-100: oklch(94.6% 0.033 307.174);
  --color-purple-200: oklch(90.2% 0.063 306.703);
  --color-purple-300: oklch(82.7% 0.119 306.383);
  --color-purple-400: oklch(71.4% 0.203 305.504);
  --color-purple-500: oklch(62.7% 0.265 303.9);
  --color-purple-600: oklch(55.8% 0.288 302.321);
  --color-purple-700: oklch(49.6% 0.265 301.924);
  --color-purple-800: oklch(43.8% 0.218 303.724);
  --color-purple-900: oklch(38.1% 0.176 304.987);
  --color-purple-950: oklch(29.1% 0.149 302.717);
  --color-fuchsia-50: oklch(97.7% 0.017 320.058);
  --color-fuchsia-100: oklch(95.2% 0.037 318.852);
  --color-fuchsia-200: oklch(90.3% 0.076 319.62);
  --color-fuchsia-300: oklch(83.3% 0.145 321.434);
  --color-fuchsia-400: oklch(74% 0.238 322.16);
  --color-fuchsia-500: oklch(66.7% 0.295 322.15);
  --color-fuchsia-600: oklch(59.1% 0.293 322.896);
  --color-fuchsia-700: oklch(51.8% 0.253 323.949);
  --color-fuchsia-800: oklch(45.2% 0.211 324.591);
  --color-fuchsia-900: oklch(40.1% 0.17 325.612);
  --color-fuchsia-950: oklch(29.3% 0.136 325.661);
  --color-pink-50: oklch(97.1% 0.014 343.198);
  --color-pink-100: oklch(94.8% 0.028 342.258);
  --color-pink-200: oklch(89.9% 0.061 343.231);
  --color-pink-300: oklch(82.3% 0.12 346.018);
  --color-pink-400: oklch(71.8% 0.202 349.761);
  --color-pink-500: oklch(65.6% 0.241 354.308);
  --color-pink-600: oklch(59.2% 0.249 0.584);
  --color-pink-700: oklch(52.5% 0.223 3.958);
  --color-pink-800: oklch(45.9% 0.187 3.815);
  --color-pink-900: oklch(40.8% 0.153 2.432);
  --color-pink-950: oklch(28.4% 0.109 3.907);
  --color-rose-50: oklch(96.9% 0.015 12.422);
  --color-rose-100: oklch(94.1% 0.03 12.58);
  --color-rose-200: oklch(89.2% 0.058 10.001);
  --color-rose-300: oklch(81% 0.117 11.638);
  --color-rose-400: oklch(71.2% 0.194 13.428);
  --color-rose-500: oklch(64.5% 0.246 16.439);
  --color-rose-600: oklch(58.6% 0.253 17.585);
  --color-rose-700: oklch(51.4% 0.222 16.935);
  --color-rose-800: oklch(45.5% 0.188 13.697);
  --color-rose-900: oklch(41% 0.159 10.272);
  --color-rose-950: oklch(27.1% 0.105 12.094);
  --color-slate-50: oklch(98.4% 0.003 247.858);
  --color-slate-100: oklch(96.8% 0.007 247.896);
  --color-slate-200: oklch(92.9% 0.013 255.508);
  --color-slate-300: oklch(86.9% 0.022 252.894);
  --color-slate-400: oklch(70.4% 0.04 256.788);
  --color-slate-500: oklch(55.4% 0.046 257.417);
  --color-slate-600: oklch(44.6% 0.043 257.281);
  --color-slate-700: oklch(37.2% 0.044 257.287);
  --color-slate-800: oklch(27.9% 0.041 260.031);
  --color-slate-900: oklch(20.8% 0.042 265.755);
  --color-slate-950: oklch(12.9% 0.042 264.695);
  --color-gray-50: oklch(98.5% 0.002 247.839);
  --color-gray-100: oklch(96.7% 0.003 264.542);
  --color-gray-200: oklch(92.8% 0.006 264.531);
  --color-gray-300: oklch(87.2% 0.01 258.338);
  --color-gray-400: oklch(70.7% 0.022 261.325);
  --color-gray-500: oklch(55.1% 0.027 264.364);
  --color-gray-600: oklch(44.6% 0.03 256.802);
  --color-gray-700: oklch(37.3% 0.034 259.733);
  --color-gray-800: oklch(27.8% 0.033 256.848);
  --color-gray-900: oklch(21% 0.034 264.665);
  --color-gray-950: oklch(13% 0.028 261.692);
  --color-zinc-50: oklch(98.5% 0 none);
  --color-zinc-100: oklch(96.7% 0.001 286.375);
  --color-zinc-200: oklch(92% 0.004 286.32);
  --color-zinc-300: oklch(87.1% 0.006 286.286);
  --color-zinc-400: oklch(70.5% 0.015 286.067);
  --color-zinc-500: oklch(55.2% 0.016 285.938);
  --color-zinc-600: oklch(44.2% 0.017 285.786);
  --color-zinc-700: oklch(37% 0.013 285.805);
  --color-zinc-800: oklch(27.4% 0.006 286.033);
  --color-zinc-900: oklch(21% 0.006 285.885);
  --color-zinc-950: oklch(14.1% 0.005 285.823);
  --color-neutral-50: oklch(98.5% 0 none);
  --color-neutral-100: oklch(97% 0 none);
  --color-neutral-200: oklch(92.2% 0 none);
  --color-neutral-300: oklch(87% 0 none);
  --color-neutral-400: oklch(70.8% 0 none);
  --color-neutral-500: oklch(55.6% 0 none);
  --color-neutral-600: oklch(43.9% 0 none);
  --color-neutral-700: oklch(37.1% 0 none);
  --color-neutral-800: oklch(26.9% 0 none);
  --color-neutral-900: oklch(20.5% 0 none);
  --color-neutral-950: oklch(14.5% 0 none);
  --color-stone-50: oklch(98.5% 0.001 106.423);
  --color-stone-100: oklch(97% 0.001 106.424);
  --color-stone-200: oklch(92.3% 0.003 48.717);
  --color-stone-300: oklch(86.9% 0.005 56.366);
  --color-stone-400: oklch(70.9% 0.01 56.259);
  --color-stone-500: oklch(55.3% 0.013 58.071);
  --color-stone-600: oklch(44.4% 0.011 73.639);
  --color-stone-700: oklch(37.4% 0.01 67.558);
  --color-stone-800: oklch(26.8% 0.007 34.298);
  --color-stone-900: oklch(21.6% 0.006 56.043);
  --color-stone-950: oklch(14.7% 0.004 49.25);
  --color-mauve-50: oklch(98.5% 0 none);
  --color-mauve-100: oklch(96% 0.003 325.6);
  --color-mauve-200: oklch(92.2% 0.005 325.62);
  --color-mauve-300: oklch(86.5% 0.012 325.68);
  --color-mauve-400: oklch(71.1% 0.019 323.02);
  --color-mauve-500: oklch(54.2% 0.034 322.5);
  --color-mauve-600: oklch(43.5% 0.029 321.78);
  --color-mauve-700: oklch(36.4% 0.029 323.89);
  --color-mauve-800: oklch(26.3% 0.024 320.12);
  --color-mauve-900: oklch(21.2% 0.019 322.12);
  --color-mauve-950: oklch(14.5% 0.008 326);
  --color-olive-50: oklch(98.8% 0.003 106.5);
  --color-olive-100: oklch(96.6% 0.005 106.5);
  --color-olive-200: oklch(93% 0.007 106.5);
  --color-olive-300: oklch(88% 0.011 106.6);
  --color-olive-400: oklch(73.7% 0.021 106.9);
  --color-olive-500: oklch(58% 0.031 107.3);
  --color-olive-600: oklch(46.6% 0.025 107.3);
  --color-olive-700: oklch(39.4% 0.023 107.4);
  --color-olive-800: oklch(28.6% 0.016 107.4);
  --color-olive-900: oklch(22.8% 0.013 107.4);
  --color-olive-950: oklch(15.3% 0.006 107.1);
  --color-mist-50: oklch(98.7% 0.002 197.1);
  --color-mist-100: oklch(96.3% 0.002 197.1);
  --color-mist-200: oklch(92.5% 0.005 214.3);
  --color-mist-300: oklch(87.2% 0.007 219.6);
  --color-mist-400: oklch(72.3% 0.014 214.4);
  --color-mist-500: oklch(56% 0.021 213.5);
  --color-mist-600: oklch(45% 0.017 213.2);
  --color-mist-700: oklch(37.8% 0.015 216);
  --color-mist-800: oklch(27.5% 0.011 216.9);
  --color-mist-900: oklch(21.8% 0.008 223.9);
  --color-mist-950: oklch(14.8% 0.004 228.8);
  --color-taupe-50: oklch(98.6% 0.002 67.8);
  --color-taupe-100: oklch(96% 0.002 17.2);
  --color-taupe-200: oklch(92.2% 0.005 34.3);
  --color-taupe-300: oklch(86.8% 0.007 39.5);
  --color-taupe-400: oklch(71.4% 0.014 41.2);
  --color-taupe-500: oklch(54.7% 0.021 43.1);
  --color-taupe-600: oklch(43.8% 0.017 39.3);
  --color-taupe-700: oklch(36.7% 0.016 35.7);
  --color-taupe-800: oklch(26.8% 0.011 36.5);
  --color-taupe-900: oklch(21.4% 0.009 43.1);
  --color-taupe-950: oklch(14.7% 0.004 49.3);
  --color-black: #000;
  --color-white: #fff;
  --spacing: 0.25rem;
  --breakpoint-sm: 40rem;
  --breakpoint-md: 48rem;
  --breakpoint-lg: 64rem;
  --breakpoint-xl: 80rem;
  --breakpoint-2xl: 96rem;
  --container-3xs: 16rem;
  --container-2xs: 18rem;
  --container-xs: 20rem;
  --container-sm: 24rem;
  --container-md: 28rem;
  --container-lg: 32rem;
  --container-xl: 36rem;
  --container-2xl: 42rem;
  --container-3xl: 48rem;
  --container-4xl: 56rem;
  --container-5xl: 64rem;
  --container-6xl: 72rem;
  --container-7xl: 80rem;
  --text-xs: 0.75rem;
  --text-xs--line-height: calc(1 / 0.75);
  --text-sm: 0.875rem;
  --text-sm--line-height: calc(1.25 / 0.875);
  --text-base: 1rem;
  --text-base--line-height: calc(1.5 / 1);
  --text-lg: 1.125rem;
  --text-lg--line-height: calc(1.75 / 1.125);
  --text-xl: 1.25rem;
  --text-xl--line-height: calc(1.75 / 1.25);
  --text-2xl: 1.5rem;
  --text-2xl--line-height: calc(2 / 1.5);
  --text-3xl: 1.875rem;
  --text-3xl--line-height: calc(2.25 / 1.875);
  --text-4xl: 2.25rem;
  --text-4xl--line-height: calc(2.5 / 2.25);
  --text-5xl: 3rem;
  --text-5xl--line-height: 1;
  --text-6xl: 3.75rem;
  --text-6xl--line-height: 1;
  --text-7xl: 4.5rem;
  --text-7xl--line-height: 1;
  --text-8xl: 6rem;
  --text-8xl--line-height: 1;
  --text-9xl: 8rem;
  --text-9xl--line-height: 1;
  --font-weight-thin: 100;
  --font-weight-extralight: 200;
  --font-weight-light: 300;
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;
  --font-weight-black: 900;
  --tracking-tighter: -0.05em;
  --tracking-tight: -0.025em;
  --tracking-normal: 0em;
  --tracking-wide: 0.025em;
  --tracking-wider: 0.05em;
  --tracking-widest: 0.1em;
  --leading-tight: 1.25;
  --leading-snug: 1.375;
  --leading-normal: 1.5;
  --leading-relaxed: 1.625;
  --leading-loose: 2;
  --radius-xs: 0.125rem;
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;
  --radius-2xl: 1rem;
  --radius-3xl: 1.5rem;
  --radius-4xl: 2rem;
  --shadow-2xs: 0 1px rgb(0 0 0 / 0.05);
  --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
  --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
  --inset-shadow-2xs: inset 0 1px rgb(0 0 0 / 0.05);
  --inset-shadow-xs: inset 0 1px 1px rgb(0 0 0 / 0.05);
  --inset-shadow-sm: inset 0 2px 4px rgb(0 0 0 / 0.05);
  --drop-shadow-xs: 0 1px 1px rgb(0 0 0 / 0.05);
  --drop-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15);
  --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12);
  --drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);
  --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1);
  --drop-shadow-2xl: 0 25px 25px rgb(0 0 0 / 0.15);
  --text-shadow-2xs: 0px 1px 0px rgb(0 0 0 / 0.15);
  --text-shadow-xs: 0px 1px 1px rgb(0 0 0 / 0.2);
  --text-shadow-sm: 0px 1px 0px rgb(0 0 0 / 0.075), 0px 1px 1px rgb(0 0 0 / 0.075), 0px 2px 2px rgb(0 0 0 / 0.075);
  --text-shadow-md: 0px 1px 1px rgb(0 0 0 / 0.1), 0px 1px 2px rgb(0 0 0 / 0.1), 0px 2px 4px rgb(0 0 0 / 0.1);
  --text-shadow-lg: 0px 1px 2px rgb(0 0 0 / 0.1), 0px 3px 2px rgb(0 0 0 / 0.1), 0px 4px 8px rgb(0 0 0 / 0.1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --animate-spin: spin 1s linear infinite;
  --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
  --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  --animate-bounce: bounce 1s infinite;
  --blur-xs: 4px;
  --blur-sm: 8px;
  --blur-md: 12px;
  --blur-lg: 16px;
  --blur-xl: 24px;
  --blur-2xl: 40px;
  --blur-3xl: 64px;
  --perspective-dramatic: 100px;
  --perspective-near: 300px;
  --perspective-normal: 500px;
  --perspective-midrange: 800px;
  --perspective-distant: 1200px;
  --aspect-video: 16 / 9;
  --default-transition-duration: 150ms;
  --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  --default-font-family: var(--font-sans);
  --default-mono-font-family: var(--font-mono);
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
@keyframes ping {
  75%, 100% {
    transform: scale(2);
    opacity: 0;
  }
}
@keyframes pulse {
  50% {
    opacity: 0.5;
  }
}
@keyframes bounce {
  0%, 100% {
    transform: translateY(-25%);
    animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
  }
  50% {
    transform: none;
    animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
  }
}

@layer components {

  /* ================================================
     DESIGN TOKENS

     Two tiers:

       1. Tailwind's own theme variables — --color-*,
          --text-*, --font-weight-*, --radius-*,
          --shadow-*, --leading-*, --spacing — are the
          source of truth, defined in the companion
          tailwind.theme.css. Referencing them (rather
          than copying their values) keeps this
          stylesheet in lockstep with the utility
          classes students write in their HTML, and
          means retheming one rethemes both.

       2. The --fd-* tokens below name those values for
          the roles this stylesheet plays. Every rule
          further down references a --fd-* token or a
          Tailwind variable, never a raw literal — so
          retheming means editing this block only.

     Custom properties only — these produce no visible
     styling on their own, so they stay unscoped.
  =================================================== */

  :root {
    /* Neutrals — Tailwind's zinc ramp */
    --fd-gray-50:  var(--color-zinc-50);
    --fd-gray-100: var(--color-zinc-100);
    --fd-gray-200: var(--color-zinc-200);
    --fd-gray-300: var(--color-zinc-300);
    --fd-gray-400: var(--color-zinc-400);
    --fd-gray-500: var(--color-zinc-500);
    --fd-gray-600: var(--color-zinc-600);
    --fd-gray-700: var(--color-zinc-700);
    --fd-gray-800: var(--color-zinc-800);
    --fd-gray-900: var(--color-zinc-900);

    --fd-surface:    var(--color-white); /* cards, inputs, menus, header */
    --fd-on-primary: var(--color-white); /* text on a filled accent background */

    /* Accent */
    --fd-primary:       var(--color-blue-600);
    --fd-primary-hover: var(--color-blue-700);
    --fd-primary-faint: var(--color-blue-50);

    /* Feedback */
    --fd-danger:         var(--color-red-600);
    --fd-danger-faint:   var(--color-red-50);
    --fd-danger-border:  var(--color-red-200);
    --fd-danger-text:    var(--color-red-800);
    --fd-success:        var(--color-green-600);
    --fd-success-faint:  var(--color-green-50);
    --fd-success-border: var(--color-green-200);
    --fd-success-text:   var(--color-green-800);

    /* Modal scrim — always dark, so it does not flip with the theme */
    --fd-backdrop: color-mix(in oklab, var(--color-zinc-900) 60%, transparent);

    /* Focus rings, derived from the accent so they follow it into dark mode */
    --fd-ring:        0 0 0 3px color-mix(in oklab, var(--fd-primary) 15%, transparent);
    --fd-ring-danger: 0 0 0 3px color-mix(in oklab, var(--fd-danger) 15%, transparent);

    /* Radii — named by role rather than by size, because Tailwind
       renumbered the scale in v4 (what v3 called rounded-sm is now
       rounded-xs), so a size name here would invite mismatches */
    --fd-radius-card:    var(--radius-lg); /* rounded-lg */
    --fd-radius-control: var(--radius-md); /* rounded-md */
    --fd-radius-inline:  var(--radius-sm); /* rounded-sm */

    /* Elevation. NB: Tailwind v4's --shadow-sm is heavier than v3's;
       the hairline shadow we want is now --shadow-xs */
    --fd-shadow-raised:  var(--shadow-xs);
    --fd-shadow-overlay: var(--shadow-lg);
    --fd-shadow-modal:   var(--shadow-xl);

    /* Spacing. --spacing is Tailwind's 0.25rem base unit — the same
       one p-4 / mb-6 / gap-2 are built from — so these line up
       exactly with the utilities, and every measurement below stays
       on that grid instead of drifting to arbitrary values. */
    --fd-gutter:      calc(var(--spacing) * 4);  /* 1rem    — page/container side padding */
    --fd-card-px:     calc(var(--spacing) * 5);  /* 1.25rem */
    --fd-card-py:     calc(var(--spacing) * 5);  /* 1.25rem */
    --fd-control-px:  calc(var(--spacing) * 3);  /* 0.75rem — buttons, inputs, nav links */
    --fd-control-py:  calc(var(--spacing) * 2);  /* 0.5rem  */
    --fd-stack-tight: calc(var(--spacing) * 3);  /* 0.75rem — headings to their body text */
    --fd-stack:       calc(var(--spacing) * 4);  /* 1rem    — between flowing blocks */
    --fd-stack-loose: calc(var(--spacing) * 6);  /* 1.5rem  — between cards */
    --fd-section:     calc(var(--spacing) * 12); /* 3rem    — page top/bottom bands */
  }

  /* Dark theme: flip the gray ramp and swap surfaces. Activated by the
     dark-mode Stimulus controller stamping data-theme="dark" on <html>.
     Custom properties only — inert until the attribute is set.

     Tailwind's own `dark:` variant keys off prefers-color-scheme, so it
     will NOT follow this toggle unless the page also declares:

       @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));

     inside its <style type="text/tailwindcss"> block. */
  [data-theme="dark"] {
    color-scheme: dark; /* native form controls, scrollbars, backdrops */

    --fd-gray-50:  var(--color-zinc-900);
    --fd-gray-100: var(--color-zinc-700);
    --fd-gray-200: var(--color-zinc-700);
    --fd-gray-300: var(--color-zinc-600);
    --fd-gray-400: var(--color-zinc-500);
    --fd-gray-500: var(--color-zinc-400);
    --fd-gray-600: var(--color-zinc-300);
    --fd-gray-700: var(--color-zinc-200);
    --fd-gray-800: var(--color-zinc-100);
    --fd-gray-900: var(--color-zinc-50);

    --fd-surface: var(--color-zinc-800);

    --fd-primary:       var(--color-blue-500); /* better contrast on dark */
    --fd-primary-hover: var(--color-blue-400);
    --fd-primary-faint: color-mix(in oklab, var(--color-blue-500) 15%, transparent);
  }

  /* ================================================
     PAGE STRUCTURE (sticky footer)
  =================================================== */

  body.appdev-styles {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    background-color: var(--fd-gray-50);
    color: var(--fd-gray-800);
  }

  body.appdev-styles > header {
    background-color: var(--fd-surface);
    border-bottom: 1px solid var(--fd-gray-200);
  }

  body.appdev-styles > main {
    flex: 1;
    padding-top: var(--fd-stack-loose);
    padding-bottom: var(--fd-section);
  }

  body.appdev-styles > footer {
    margin-top: auto;
    padding-top: var(--fd-section);
    padding-bottom: var(--fd-section);
    background-color: var(--fd-gray-200);
    border-top: 1px solid var(--fd-gray-300);
    color: var(--fd-gray-600);
    font-size: var(--text-sm);
  }

  body.appdev-styles > footer a {
    color: var(--fd-gray-700);
    text-decoration: none;
  }

  body.appdev-styles > footer a:hover {
    color: var(--fd-gray-900);
    text-decoration: underline;
  }

  /* ================================================
     CONTAINERS
  =================================================== */

  /* Full-width responsive container. (When the Tailwind browser build is
     active, its own `container` utility supplies max-widths per breakpoint;
     these centering/padding rules compose with it.) */
  body.appdev-styles .container {
    width: 100%;
    max-width: var(--container-7xl);
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--fd-gutter);
    padding-right: var(--fd-gutter);
  }

  body.appdev-styles .container-half,
  body.appdev-styles .container-two-thirds {
    width: 100%;
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--fd-gutter);
    padding-right: var(--fd-gutter);
  }

  /* Breakpoints are written in rem to match Tailwind's own --breakpoint-*
     values (md/lg/xl/2xl), so these containers step at the same widths as
     the md: / lg: / xl: / 2xl: variants. Media queries can't read var(),
     so the numbers are spelled out. */
  @media (width >= 48rem) { /* --breakpoint-md */
    body.appdev-styles .container-half        { max-width: 350px; }
    body.appdev-styles .container-two-thirds  { max-width: 467px; }
  }

  @media (width >= 64rem) { /* --breakpoint-lg */
    body.appdev-styles .container-half        { max-width: 475px; }
    body.appdev-styles .container-two-thirds  { max-width: 633px; }
  }

  @media (width >= 80rem) { /* --breakpoint-xl */
    body.appdev-styles .container-half        { max-width: 600px; }
    body.appdev-styles .container-two-thirds  { max-width: 800px; }
  }

  @media (width >= 96rem) { /* --breakpoint-2xl */
    body.appdev-styles .container-half        { max-width: 725px; }
    body.appdev-styles .container-two-thirds  { max-width: 967px; }
  }

  /* ================================================
     TYPOGRAPHY
  =================================================== */

  body.appdev-styles h1,
  body.appdev-styles h2,
  body.appdev-styles h3,
  body.appdev-styles h4,
  body.appdev-styles h5,
  body.appdev-styles h6 {
    font-weight: var(--font-weight-semibold);
    line-height: var(--leading-tight);
    color: var(--fd-gray-900);
    margin-bottom: var(--fd-stack-tight);
  }

  body.appdev-styles h1 { font-size: var(--text-3xl); }
  body.appdev-styles h2 { font-size: var(--text-2xl); }
  body.appdev-styles h3 { font-size: var(--text-xl); }
  body.appdev-styles h4 { font-size: var(--text-lg); }

  body.appdev-styles p {
    margin-bottom: var(--fd-stack);
  }

  body.appdev-styles main a {
    color: var(--fd-primary);
    text-decoration: none;
  }

  body.appdev-styles main a:hover {
    text-decoration: underline;
  }

  /* Bulleted lists in flowing content (cards, navs, and
     breadcrumbs override this further down) */
  body.appdev-styles main ul {
    list-style: disc;
    padding-left: var(--fd-stack-loose);
    margin-bottom: var(--fd-stack);
  }

  body.appdev-styles main ul ul {
    list-style: circle;
    margin-top: calc(var(--spacing) * 1);
    margin-bottom: 0;
  }

  body.appdev-styles main li {
    margin-bottom: calc(var(--spacing) * 1);
  }

  body.appdev-styles hr {
    border: 0;
    border-top: 1px solid var(--fd-gray-200);
    margin: calc(var(--spacing) * 8) 0;
  }

  body.appdev-styles code {
    background-color: var(--fd-gray-100);
    border: 1px solid var(--fd-gray-200);
    border-radius: var(--fd-radius-inline);
    padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 1.5);
    font-size: 0.875em; /* em, so inline code tracks its surrounding text */
  }

  body.appdev-styles pre {
    background-color: var(--fd-gray-100);
    border: 1px solid var(--fd-gray-200);
    border-radius: var(--fd-radius-control);
    padding: var(--fd-stack);
    overflow-x: auto;
    margin-bottom: var(--fd-stack);
    font-size: var(--text-sm);
    line-height: var(--leading-relaxed);
  }

  body.appdev-styles pre code {
    background-color: transparent;
    border: 0;
    padding: 0;
    font-size: inherit;
  }

  body.appdev-styles figure {
    margin-bottom: var(--fd-stack);
  }

  /* Description lists — bold terms, tight spacing */
  body.appdev-styles dt {
    font-weight: var(--font-weight-semibold);
    color: var(--fd-gray-900);
  }

  body.appdev-styles dd {
    margin: 0 0 var(--fd-stack-tight);
  }

  body.appdev-styles dd > p:last-child {
    margin-bottom: 0;
  }

  /* ================================================
     NAVBAR  (body > header > ... > nav)
  =================================================== */

  body.appdev-styles > header nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    min-height: calc(var(--spacing) * 14); /* 3.5rem */
  }

  body.appdev-styles > header nav ul {
    display: flex;
    align-items: center;
    gap: calc(var(--spacing) * 1);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  /* The links' own padding (for the hover pill) would push their text
     inward; pull the outer edges back so the navbar text lines up with
     the page content */
  body.appdev-styles > header nav > ul:first-child {
    margin-left: calc(var(--fd-control-px) * -1);
  }

  body.appdev-styles > header nav > ul:last-child {
    margin-right: calc(var(--fd-control-px) * -1);
  }

  body.appdev-styles > header nav li {
    margin: 0;
  }

  body.appdev-styles > header nav a {
    display: block;
    padding: var(--fd-control-py) var(--fd-control-px);
    border-radius: var(--fd-radius-control);
    color: var(--fd-gray-600);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
  }

  body.appdev-styles > header nav a:hover {
    color: var(--fd-gray-900);
    background-color: var(--fd-gray-100);
  }

  body.appdev-styles > header nav strong a {
    color: var(--fd-gray-900);
    font-weight: var(--font-weight-bold);
  }

  /* Secondary horizontal navs inside the page (e.g. admin
     section nav) */
  body.appdev-styles main nav:not([aria-label="breadcrumb"], .pagy) ul {
    display: flex;
    flex-wrap: wrap;
    gap: calc(var(--spacing) * 1);
    list-style: none;
    margin: 0 0 calc(var(--spacing) * 2) calc(var(--fd-control-px) * -1);
    padding: 0;
  }

  body.appdev-styles main nav:not([aria-label="breadcrumb"], .pagy) li {
    margin: 0;
  }

  body.appdev-styles main nav:not([aria-label="breadcrumb"], .pagy) a {
    display: block;
    padding: calc(var(--spacing) * 1.5) var(--fd-control-px);
    border-radius: var(--fd-radius-control);
    font-size: var(--text-sm);
    font-weight: var(--font-weight-medium);
  }

  body.appdev-styles main nav:not([aria-label="breadcrumb"], .pagy) a:hover {
    background-color: var(--fd-gray-100);
    text-decoration: none;
  }

  /* ================================================
     BREADCRUMBS
  =================================================== */

  body.appdev-styles nav[aria-label="breadcrumb"] ul {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    list-style: none;
    margin: 0 0 var(--fd-stack);
    padding: 0;
    font-size: var(--text-sm);
    color: var(--fd-gray-500);
  }

  body.appdev-styles nav[aria-label="breadcrumb"] li {
    margin: 0;
  }

  body.appdev-styles nav[aria-label="breadcrumb"] li + li::before {
    content: "›";
    margin: 0 calc(var(--spacing) * 2);
    color: var(--fd-gray-400);
  }

  /* ================================================
     CARDS  (<article> or .card)

     Two ways to write the same card, styled identically:

       <article> ... </article>
       <div class="card"> ... </div>

     <article> keeps the classless story intact for hand-written
     semantic HTML. .card is what generated markup emits, so a
     student who wants to style a card themselves can delete one
     word instead of opting out of the whole stylesheet.

     Every selector below is therefore written twice. Do NOT collapse
     the pairs into :is(article, .card) — :is() takes the highest
     specificity in its list, which would silently promote the
     <article> rules from 0,1,2 to 0,2,1.
  =================================================== */

  body.appdev-styles article,
  body.appdev-styles .card {
    background-color: var(--fd-surface);
    border: 1px solid var(--fd-gray-200);
    border-radius: var(--fd-radius-card);
    box-shadow: var(--fd-shadow-raised);
    padding: var(--fd-card-py) var(--fd-card-px);
    margin-bottom: var(--fd-stack-loose);
  }

  body.appdev-styles article > :last-child,
  body.appdev-styles .card > :last-child {
    margin-bottom: 0;
  }

  /* Card header strip */
  body.appdev-styles article > header,
  body.appdev-styles .card > header {
    margin: calc(var(--fd-card-py) * -1) calc(var(--fd-card-px) * -1) var(--fd-card-py);
    padding: calc(var(--spacing) * 3.5) var(--fd-card-px);
    background-color: var(--fd-gray-50);
    border-bottom: 1px solid var(--fd-gray-200);
    border-radius: calc(var(--fd-radius-card) - 1px) calc(var(--fd-radius-card) - 1px) 0 0;
  }

  body.appdev-styles article > header :is(h1, h2, h3, h4, h5, h6),
  body.appdev-styles .card > header :is(h1, h2, h3, h4, h5, h6) {
    margin: 0;
  }

  body.appdev-styles article > header > :last-child,
  body.appdev-styles .card > header > :last-child {
    margin-bottom: 0;
  }

  /* When a flush list group directly follows the card header, close the
     gap so the header sits flush against the first list item */
  body.appdev-styles article > header:has(+ ul),
  body.appdev-styles .card > header:has(+ ul) {
    margin-bottom: 0;
  }

  /* Flush list group — a <ul> that is a direct child of a card */
  body.appdev-styles article > ul,
  body.appdev-styles .card > ul {
    list-style: none;
    margin: 0 calc(var(--fd-card-px) * -1);
    padding: 0;
  }

  body.appdev-styles article > ul > li,
  body.appdev-styles .card > ul > li {
    margin: 0;
    padding: var(--fd-stack-tight) var(--fd-card-px);
    border-bottom: 1px solid var(--fd-gray-200);
  }

  body.appdev-styles article > ul > li:first-child,
  body.appdev-styles .card > ul > li:first-child {
    border-top: 1px solid var(--fd-gray-200);
  }

  /* The card header's own border already divides it from the first item */
  body.appdev-styles article > header + ul > li:first-child,
  body.appdev-styles .card > header + ul > li:first-child {
    border-top: 0;
  }

  body.appdev-styles article > ul > li > :last-child,
  body.appdev-styles .card > ul > li > :last-child {
    margin-bottom: 0;
  }

  /* List group action items — a list item whose only content
     is a single link becomes fully clickable */
  body.appdev-styles article > ul > li:has(> a:only-child),
  body.appdev-styles .card > ul > li:has(> a:only-child) {
    padding: 0;
  }

  body.appdev-styles article > ul > li > a:only-child,
  body.appdev-styles .card > ul > li > a:only-child {
    display: flex;
    align-items: center;
    gap: var(--fd-stack);
    padding: var(--fd-stack-tight) var(--fd-card-px);
    color: inherit;
    text-decoration: none;
  }

  body.appdev-styles article > ul > li > a:only-child img,
  body.appdev-styles .card > ul > li > a:only-child img {
    flex-shrink: 0;
    border-radius: var(--fd-radius-control);
  }

  body.appdev-styles article > ul > li > a:only-child::after,
  body.appdev-styles .card > ul > li > a:only-child::after {
    content: "›";
    font-size: var(--text-2xl);
    line-height: 1;
    color: var(--fd-gray-400);
    margin-left: auto;
  }

  body.appdev-styles article > ul > li > a:only-child:hover,
  body.appdev-styles article > ul > li > a:only-child[aria-current="page"],
  body.appdev-styles .card > ul > li > a:only-child:hover,
  body.appdev-styles .card > ul > li > a:only-child[aria-current="page"] {
    background-color: var(--fd-primary-faint);
    color: var(--fd-primary-hover);
  }

  body.appdev-styles article > ul > li > a:only-child:hover::after,
  body.appdev-styles article > ul > li > a:only-child[aria-current="page"]::after,
  body.appdev-styles .card > ul > li > a:only-child:hover::after,
  body.appdev-styles .card > ul > li > a:only-child[aria-current="page"]::after {
    color: var(--fd-primary-hover);
  }

  /* ================================================
     TABLES
  =================================================== */

  body.appdev-styles table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: var(--fd-stack);
  }

  body.appdev-styles th {
    text-align: left;
    font-weight: var(--font-weight-semibold);
    font-size: var(--text-sm);
    color: var(--fd-gray-600);
    padding: var(--fd-stack-tight) var(--fd-stack);
    border-bottom: 1px solid var(--fd-gray-300);
    background-color: var(--fd-gray-50);
  }

  body.appdev-styles td {
    padding: var(--fd-stack-tight) var(--fd-stack);
    border-bottom: 1px solid var(--fd-gray-200);
  }

  body.appdev-styles th a {
    color: inherit;
  }

  /* Flush tables inside cards */
  body.appdev-styles article > table,
  body.appdev-styles article > .overflow-auto,
  body.appdev-styles .card > table,
  body.appdev-styles .card > .overflow-auto {
    margin-left: calc(var(--fd-card-px) * -1);
    margin-right: calc(var(--fd-card-px) * -1);
  }

  body.appdev-styles article > table,
  body.appdev-styles .card > table {
    width: calc(100% + var(--fd-card-px) * 2);
  }

  body.appdev-styles article :is(th, td):first-child,
  body.appdev-styles .card :is(th, td):first-child {
    padding-left: var(--fd-card-px);
  }

  body.appdev-styles article :is(th, td):last-child,
  body.appdev-styles .card :is(th, td):last-child {
    padding-right: var(--fd-card-px);
  }

  /* ================================================
     FORMS
  =================================================== */

  body.appdev-styles label,
  body.appdev-styles legend {
    display: block;
    font-weight: var(--font-weight-medium);
    font-size: var(--text-sm);
    color: var(--fd-gray-700);
    margin-bottom: calc(var(--spacing) * 1.5);
  }

  /* The :not() list is wrapped in :where() so it adds no specificity —
     named components like .form-control can override these defaults */
  body.appdev-styles input:where(:not([type="checkbox"], [type="radio"], [type="submit"], [type="button"])),
  body.appdev-styles select,
  body.appdev-styles textarea {
    display: block;
    width: 100%;
    padding: var(--fd-control-py) var(--fd-control-px);
    background-color: var(--fd-surface);
    border: 1px solid var(--fd-gray-300);
    border-radius: var(--fd-radius-control);
    box-shadow: var(--fd-shadow-raised);
    margin-bottom: var(--fd-stack);
  }

  body.appdev-styles input:where(:not([type="checkbox"], [type="radio"], [type="submit"], [type="button"])):focus,
  body.appdev-styles select:focus,
  body.appdev-styles textarea:focus {
    outline: none;
    border-color: var(--fd-primary);
    box-shadow: var(--fd-ring);
  }

  body.appdev-styles ::placeholder {
    color: var(--fd-gray-400);
  }

  body.appdev-styles input[type="checkbox"],
  body.appdev-styles input[type="radio"] {
    width: calc(var(--spacing) * 4);
    height: calc(var(--spacing) * 4);
    accent-color: var(--fd-primary);
    margin-right: calc(var(--spacing) * 1);
  }

  /* Labels that sit next to a checkbox or radio stay inline */
  body.appdev-styles input[type="checkbox"] + label,
  body.appdev-styles input[type="radio"] + label,
  body.appdev-styles label:has(> input[type="checkbox"]),
  body.appdev-styles label:has(> input[type="radio"]) {
    display: inline-block;
    font-weight: var(--font-weight-normal);
    font-size: var(--text-base);
    color: inherit;
    margin-right: var(--fd-stack);
  }

  body.appdev-styles fieldset {
    border: 0;
    margin: 0 0 var(--fd-stack);
    padding: 0;
    min-width: 0;
  }

  /* Collapsible sections (e.g. filter forms) */
  body.appdev-styles summary {
    cursor: pointer;
    font-weight: var(--font-weight-medium);
    color: var(--fd-gray-700);
  }

  body.appdev-styles summary:hover {
    color: var(--fd-gray-900);
  }

  body.appdev-styles details[open] > summary {
    margin-bottom: var(--fd-stack);
  }

  /* ================================================
     BUTTONS
  =================================================== */

  body.appdev-styles button,
  body.appdev-styles input[type="submit"],
  body.appdev-styles input[type="button"],
  body.appdev-styles .btn {
    display: inline-block;
    padding: var(--fd-control-py) var(--fd-stack);
    background-color: var(--fd-primary);
    color: var(--fd-on-primary);
    font-weight: var(--font-weight-medium);
    font-size: var(--text-base);
    text-align: center;
    text-decoration: none;
    border: 1px solid transparent;
    border-radius: var(--fd-radius-control);
    box-shadow: var(--fd-shadow-raised);
    cursor: pointer;
  }

  body.appdev-styles button:hover,
  body.appdev-styles input[type="submit"]:hover,
  body.appdev-styles input[type="button"]:hover,
  body.appdev-styles .btn:hover {
    background-color: var(--fd-primary-hover);
  }

  body.appdev-styles main a.btn:hover {
    text-decoration: none;
  }

  /* Submit buttons span the full width of their form */
  body.appdev-styles form button[type="submit"],
  body.appdev-styles form input[type="submit"] {
    width: 100%;
  }

  body.appdev-styles .btn-outline {
    background-color: var(--fd-surface);
    color: var(--fd-gray-700);
    border-color: var(--fd-gray-300);
  }

  body.appdev-styles .btn-outline:hover {
    background-color: var(--fd-gray-100);
    color: var(--fd-gray-900);
  }

  /* ================================================
     MODALS  (native <dialog> + modal Stimulus controller)

     Expected structure:
       <div data-controller="modal">
         <button data-action="click->modal#open">Open</button>
         <dialog data-modal-target="dialog">
           <div class="card"> ... card content ... </div>
         </dialog>
       </div>

     The card inside (<div class="card"> or <article>) picks up the
     regular card styling;
     these rules handle sizing, the backdrop, the close (X)
     button, and open/close animations driven by the
     modal-is-open/-opening/-closing classes the controller
     toggles on <html>.
  =================================================== */

  /* Lock page scrolling while a modal is open */
  html.modal-is-open:has(body.appdev-styles) {
    overflow: hidden;
  }

  body.appdev-styles dialog {
    width: calc(100% - var(--spacing) * 8);
    max-width: var(--container-lg);
    margin: auto;
    padding: 0;
    border: 0;
    background: transparent;
  }

  body.appdev-styles dialog::backdrop {
    background-color: var(--fd-backdrop);
  }

  body.appdev-styles dialog > article,
  body.appdev-styles dialog > .card {
    margin: 0;
    max-height: calc(100dvh - var(--spacing) * 16);
    overflow-y: auto;
    box-shadow: var(--fd-shadow-modal);
  }

  /* The close (X) button: an empty <button aria-label="Close">
     in the card header */
  body.appdev-styles dialog button[aria-label="Close"] {
    float: right;
    display: flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--spacing) * 7);  /* 1.75rem */
    height: calc(var(--spacing) * 7);
    margin: 0 0 0 calc(var(--spacing) * 2);
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fd-radius-control);
    box-shadow: none;
    color: var(--fd-gray-500);
    font-size: var(--text-2xl);
    line-height: 1;
    cursor: pointer;
  }

  body.appdev-styles dialog button[aria-label="Close"]::before {
    content: "\00d7"; /* × */
  }

  body.appdev-styles dialog button[aria-label="Close"]:hover {
    background-color: var(--fd-gray-200);
    color: var(--fd-gray-900);
  }

  /* Action buttons (Close/Cancel/Confirm) that follow other modal
     content get breathing room above them. (Buttons are inline-block,
     so this margin doesn't collapse with the preceding element's.) */
  body.appdev-styles dialog article * + button,
  body.appdev-styles dialog .card * + button {
    margin-top: var(--fd-stack);
  }

  /* A full-width content hr reads as a footer divider inside a modal;
     tighten its margins to fit the card */
  body.appdev-styles dialog article hr,
  body.appdev-styles dialog .card hr {
    margin: var(--fd-stack) 0;
  }

  /* Open/close animations (the controller adds these classes
     to <html> and waits for the animation before closing) */
  html.modal-is-opening body.appdev-styles dialog[open] {
    animation: fd-modal-pop 0.2s ease-out;
  }

  html.modal-is-opening body.appdev-styles dialog[open]::backdrop {
    animation: fd-modal-fade 0.2s ease-out;
  }

  html.modal-is-closing body.appdev-styles dialog[open] {
    animation: fd-modal-pop 0.2s ease-in reverse forwards;
  }

  html.modal-is-closing body.appdev-styles dialog[open]::backdrop {
    animation: fd-modal-fade 0.2s ease-in reverse forwards;
  }

  @keyframes fd-modal-fade {
    from { opacity: 0; }
  }

  @keyframes fd-modal-pop {
    from {
      opacity: 0;
      transform: translateY(calc(var(--spacing) * -3)) scale(0.98);
    }
  }

  /* ================================================
     PAGINATION  (Pagy series_nav)
  =================================================== */

  body.appdev-styles nav.pagy {
    display: flex;
    justify-content: center;
    margin-top: var(--fd-stack-loose);
  }

  body.appdev-styles nav.pagy a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: calc(var(--spacing) * 10); /* 2.5rem */
    height: calc(var(--spacing) * 10);
    padding: calc(var(--spacing) * 1.5) var(--fd-control-px);
    margin-left: -1px;
    background-color: var(--fd-surface);
    border: 1px solid var(--fd-gray-300);
    color: var(--fd-primary);
    font-size: var(--text-sm);
    text-decoration: none;
  }

  body.appdev-styles nav.pagy a:first-child {
    margin-left: 0;
    border-top-left-radius: var(--fd-radius-control);
    border-bottom-left-radius: var(--fd-radius-control);
  }

  body.appdev-styles nav.pagy a:last-child {
    border-top-right-radius: var(--fd-radius-control);
    border-bottom-right-radius: var(--fd-radius-control);
  }

  body.appdev-styles nav.pagy a[href]:hover {
    z-index: 2;
    position: relative;
    background-color: var(--fd-gray-100);
  }

  /* Current page */
  body.appdev-styles nav.pagy a[aria-current="page"] {
    z-index: 3;
    position: relative;
    background-color: var(--fd-primary);
    border-color: var(--fd-primary);
    color: var(--fd-on-primary);
    cursor: default;
  }

  /* Disabled prev/next and gap separators */
  body.appdev-styles nav.pagy a[aria-disabled="true"]:not([aria-current="page"]) {
    color: var(--fd-gray-400);
    cursor: not-allowed;
  }

  /* ================================================
     INDUSTRIAL COMPONENTS (Bootstrap-feel)

     Named components with Bootstrap-familiar names for
     the later, "industrial-grade" phase of the course.
     Layout and one-off styling come from Tailwind
     utilities; these cover the recurring patterns.
  =================================================== */

  /* --- Position & layout helpers (Bootstrap names) --- */

  body.appdev-styles .container-fluid {
    width: 100%;
    padding-left: var(--fd-gutter);
    padding-right: var(--fd-gutter);
  }

  body.appdev-styles .fixed-top {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 30;
  }

  body.appdev-styles .fixed-bottom {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 30;
  }

  body.appdev-styles .sticky-top {
    position: sticky;
    top: var(--fd-stack);
  }

  body.appdev-styles .bg-body-tertiary {
    background-color: var(--fd-gray-100);
  }

  body.appdev-styles .visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  body.appdev-styles .icon-link {
    display: inline-flex;
    align-items: center;
    gap: calc(var(--spacing) * 2);
  }

  /* --- Buttons --- */

  body.appdev-styles .btn-primary {
    background-color: var(--fd-primary);
    color: var(--fd-on-primary);
  }

  body.appdev-styles .btn-primary:hover {
    background-color: var(--fd-primary-hover);
  }

  body.appdev-styles .btn-secondary {
    background-color: var(--fd-gray-600);
    color: var(--fd-on-primary);
  }

  body.appdev-styles .btn-secondary:hover {
    background-color: var(--fd-gray-700);
  }

  body.appdev-styles .btn-outline-primary {
    background-color: transparent;
    color: var(--fd-primary);
    border-color: var(--fd-primary);
  }

  body.appdev-styles .btn-outline-primary:hover {
    background-color: var(--fd-primary);
    color: var(--fd-on-primary);
  }

  body.appdev-styles .btn-outline-secondary {
    background-color: var(--fd-surface);
    color: var(--fd-gray-700);
    border-color: var(--fd-gray-300);
  }

  body.appdev-styles .btn-outline-secondary:hover {
    background-color: var(--fd-gray-100);
    color: var(--fd-gray-900);
  }

  /* Link-styled buttons (icon buttons, inline actions) */
  body.appdev-styles .btn-link {
    background-color: transparent;
    border-color: transparent;
    box-shadow: none;
    color: var(--fd-primary);
    font-weight: var(--font-weight-normal);
    padding: calc(var(--spacing) * 1) calc(var(--spacing) * 2);
  }

  body.appdev-styles .btn-link:hover {
    background-color: transparent;
    color: var(--fd-primary-hover);
  }

  /* Dismiss (X) button for alerts and modals */
  body.appdev-styles .btn-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--spacing) * 7);  /* 1.75rem */
    height: calc(var(--spacing) * 7);
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: var(--fd-radius-control);
    box-shadow: none;
    color: var(--fd-gray-500);
    font-size: var(--text-2xl);
    line-height: 1;
    cursor: pointer;
  }

  body.appdev-styles .btn-close::before {
    content: "\00d7"; /* × */
  }

  body.appdev-styles .btn-close:hover {
    background-color: var(--fd-gray-200);
    color: var(--fd-gray-900);
  }

  /* Buttons with explicit component classes size to their content;
     only classless submits span the form (the classless default above) */
  body.appdev-styles form button[type="submit"]:is(.btn, .nav-link) {
    width: auto;
  }

  /* --- Forms --- */

  body.appdev-styles .form-group {
    margin-bottom: var(--fd-stack);
  }

  body.appdev-styles .form-control {
    display: block;
    width: 100%;
    padding: var(--fd-control-py) var(--fd-control-px);
    background-color: var(--fd-surface);
    border: 1px solid var(--fd-gray-300);
    border-radius: var(--fd-radius-control);
    box-shadow: var(--fd-shadow-raised);
    margin-bottom: 0;
  }

  body.appdev-styles .form-control:focus {
    outline: none;
    border-color: var(--fd-primary);
    box-shadow: var(--fd-ring);
  }

  body.appdev-styles .form-text {
    display: block;
    margin-top: calc(var(--spacing) * 1);
    font-size: var(--text-sm);
    color: var(--fd-gray-500);
  }

  body.appdev-styles .form-check {
    display: block;
  }

  body.appdev-styles .form-check-input {
    margin-right: calc(var(--spacing) * 1);
  }

  body.appdev-styles .form-check-label {
    display: inline-block;
    font-weight: var(--font-weight-normal);
    font-size: var(--text-base);
    color: inherit;
  }

  /* Validation states */
  body.appdev-styles .form-control.is-invalid {
    border-color: var(--fd-danger);
  }

  body.appdev-styles .form-control.is-invalid:focus {
    box-shadow: var(--fd-ring-danger);
  }

  body.appdev-styles .form-control.is-valid {
    border-color: var(--fd-success);
  }

  body.appdev-styles .invalid-feedback {
    margin-top: calc(var(--spacing) * 1);
    font-size: var(--text-sm);
    color: var(--fd-danger);
  }

  /* --- Alerts --- */

  body.appdev-styles .alert {
    position: relative;
    padding: var(--fd-stack-tight) var(--fd-stack);
    margin-bottom: var(--fd-stack);
    border: 1px solid transparent;
    border-radius: var(--fd-radius-control);
  }

  body.appdev-styles .alert-success {
    background-color: var(--fd-success-faint);
    border-color: var(--fd-success-border);
    color: var(--fd-success-text);
  }

  body.appdev-styles .alert-danger {
    background-color: var(--fd-danger-faint);
    border-color: var(--fd-danger-border);
    color: var(--fd-danger-text);
  }

  body.appdev-styles .alert-dismissible {
    padding-right: var(--fd-section);
  }

  body.appdev-styles .alert .btn-close {
    position: absolute;
    top: 50%;
    right: var(--fd-stack-tight);
    transform: translateY(-50%);
    color: inherit;
  }

  /* --- Badges --- */

  body.appdev-styles .badge {
    display: inline-flex;
    align-items: center;
    gap: calc(var(--spacing) * 1);
    padding: 0.25em 0.5em; /* em, so badges scale with their context */
    font-size: 0.75em;
    font-weight: var(--font-weight-semibold);
    line-height: 1;
    border-radius: var(--fd-radius-control);
  }

  body.appdev-styles .text-bg-secondary {
    background-color: var(--fd-gray-500);
    color: var(--fd-on-primary);
  }

  body.appdev-styles .text-bg-light {
    background-color: var(--fd-gray-100);
    color: var(--fd-gray-900);
    border: 1px solid var(--fd-gray-300);
  }

  /* --- List groups --- */

  body.appdev-styles .list-group {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body.appdev-styles .list-group-item {
    padding: var(--fd-stack-tight) calc(var(--spacing) * 1);
  }

  body.appdev-styles .list-group-flush > .list-group-item {
    border-bottom: 1px solid var(--fd-gray-200);
  }

  body.appdev-styles :is(.list-group-action, .list-group-action-item):hover {
    background-color: var(--fd-gray-50);
  }

  /* --- Nav & tabs --- */

  body.appdev-styles .nav {
    display: flex;
    flex-wrap: wrap;
    list-style: none;
    margin: 0;
    padding: 0;
  }

  body.appdev-styles .nav-item {
    margin: 0;
  }

  body.appdev-styles .nav-link {
    display: flex;
    align-items: center;
    gap: var(--fd-stack-tight);
    width: auto;
    padding: var(--fd-control-py) var(--fd-control-px);
    background: transparent;
    border: 0;
    border-radius: var(--fd-radius-control);
    box-shadow: none;
    color: var(--fd-gray-700);
    font-weight: var(--font-weight-medium);
    font-size: var(--text-base);
    text-align: left;
    text-decoration: none;
  }

  body.appdev-styles .nav-link:hover {
    background-color: var(--fd-gray-100);
    color: var(--fd-gray-900);
  }

  /* Underline-style tab navigation */
  body.appdev-styles .nav-underline {
    gap: var(--fd-stack);
    border-bottom: 1px solid var(--fd-gray-200);
  }

  body.appdev-styles .nav-underline .nav-link {
    padding: var(--fd-control-py) calc(var(--spacing) * 1);
    margin-bottom: -1px;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--fd-gray-500);
  }

  body.appdev-styles .nav-underline .nav-link:hover {
    background: transparent;
    color: var(--fd-gray-900);
  }

  body.appdev-styles .nav-underline .nav-link.active {
    color: var(--fd-primary);
    border-bottom-color: var(--fd-primary);
  }

  /* Tab panels: hidden by default, shown via the `active` class,
     which the tabs Stimulus controller toggles */
  body.appdev-styles .tab-pane {
    display: none;
  }

  body.appdev-styles .tab-pane.active {
    display: block;
  }

  /* --- Navbar --- */

  body.appdev-styles .navbar {
    padding: var(--fd-control-py) 0;
    background-color: var(--fd-gray-100);
    border-bottom: 1px solid var(--fd-gray-200);
  }

  body.appdev-styles .navbar > :is(.container, .container-fluid) {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
  }

  body.appdev-styles .navbar.fixed-bottom {
    border-bottom: 0;
    border-top: 1px solid var(--fd-gray-200);
  }

  body.appdev-styles .navbar-brand {
    font-size: var(--text-lg);
    font-weight: var(--font-weight-semibold);
    color: var(--fd-gray-900);
    text-decoration: none;
  }

  body.appdev-styles .navbar-nav {
    display: flex;
    list-style: none;
    margin: 0;
    padding: 0;
  }

  /* --- Dropdowns --- */

  body.appdev-styles .dropdown {
    position: relative;
  }

  /* Hidden by default, shown via the `show` class, which the
     dropdown Stimulus controller toggles */
  body.appdev-styles .dropdown-menu {
    display: none;
    position: absolute;
    z-index: 40;
    min-width: calc(var(--spacing) * 44); /* 11rem */
    margin-top: calc(var(--spacing) * 1);
    padding: calc(var(--spacing) * 1.5) 0;
    background-color: var(--fd-surface);
    border: 1px solid var(--fd-gray-200);
    border-radius: var(--fd-radius-control);
    box-shadow: var(--fd-shadow-overlay);
    list-style: none;
  }

  body.appdev-styles .dropdown-menu.show {
    display: block;
  }

  body.appdev-styles .dropdown-menu li {
    margin: 0;
  }

  body.appdev-styles .dropdown-menu form {
    margin: 0;
  }

  body.appdev-styles .dropdown-item {
    display: block;
    width: 100%;
    padding: calc(var(--spacing) * 1.5) var(--fd-stack);
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    color: var(--fd-gray-700);
    font-weight: var(--font-weight-normal);
    font-size: var(--text-base);
    text-align: left;
    text-decoration: none;
  }

  body.appdev-styles .dropdown-item:hover {
    background-color: var(--fd-gray-100);
    color: var(--fd-gray-900);
  }

  /* --- Cards --- */

  /* .card is styled in the CARDS section above, alongside <article>,
     so there is nothing to add here. It is a complete card on its own:
     one class, no inner wrapper element. (Note this differs from
     daisyUI, whose bare .card carries no background, border, padding,
     or shadow and requires a nested .card-body for padding.) */
}
