/* Aplomb — layout only. Every colour, size, radius and duration comes from tokens.css.
   Breakpoints (not expressible as variables): 600px phone, 1024px nav drawer. */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; min-height: 100vh; }
h1, h2, h3, p, ul, ol, dl, dd, figure { margin: 0; }
ul[role="list"], ol[role="list"] { list-style: none; padding: 0; }
img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: var(--foret-700); }

/* Accessibility helpers */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: var(--sp-4); top: calc(-1 * var(--topbar-height));
  z-index: var(--z-toast); padding: var(--sp-2) var(--sp-4);
  background: var(--foret-700); color: var(--sur-foret); border-radius: var(--r-card);
  transition: top var(--duration);
}
.skip-link:focus { top: var(--sp-2); }

/* Layout primitives */
.container { width: 100%; max-width: var(--content-max); margin-inline: auto; padding-inline: var(--sp-4); }
.stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.stack--tight { gap: var(--sp-2); }
.stack--loose { gap: var(--sp-8); }
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.cluster--spread { justify-content: space-between; }
.grid-auto { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr)); }

@media (min-width: 600px) {
  .container { padding-inline: var(--sp-6); }
}

[x-cloak] { display: none !important; }

/* ------------------------------------------------------------------------- */
/* Office shell: top bar + left nav (drawer below 1024px)                     */
/* ------------------------------------------------------------------------- */

.app-shell { min-height: 100vh; }

.topbar {
  position: sticky; top: 0; z-index: var(--z-topbar);
  display: flex; align-items: center; gap: var(--sp-3);
  height: var(--topbar-height); padding-inline: var(--sp-4);
  background: var(--surface); border-bottom: var(--hairline);
}
.topbar__brand { text-decoration: none; }
.topbar__project { min-width: 0; }
.topbar__project-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar__end { margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
.topbar__user { display: none; }

.sidenav {
  position: fixed; inset-block: 0; left: 0; z-index: var(--z-drawer);
  width: var(--nav-width); overflow-y: auto;
  padding: var(--sp-4) var(--sp-3) var(--sp-8);
  background: var(--surface); border-right: var(--hairline);
  transform: translateX(-100%); visibility: hidden;
  transition: transform var(--duration), visibility var(--duration);
}
.sidenav.is-open { transform: none; visibility: visible; }
.sidenav__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-4); }
.sidenav__group + .sidenav__group { margin-top: var(--sp-6); }
.sidenav__title {
  margin: 0 0 var(--sp-1); padding-inline: var(--sp-3);
  font: 500 var(--fs-micro)/var(--lh-micro) var(--font-ui); color: var(--beton-500);
  transition: color var(--duration);
}
/* Twenty links in one column: the quarter of the day you are in is named before you read a word. */
.sidenav__group.is-active > .sidenav__title { color: var(--foret-700); }

/* A link is an icon and a label. The icon is decorative — the label is always written — so it
   carries the colour and the movement, and the label carries the meaning. */
.sidenav__link {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--control-height); padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-field);
  color: var(--beton-700); text-decoration: none; font-size: var(--fs-small);
  transition: background var(--duration), color var(--duration);
}
.sidenav__link > .icon { flex: none; color: var(--beton-500); transition: color var(--duration), transform var(--duration); }
.sidenav__label { min-width: 0; }

a.sidenav__link:hover { background: var(--sable-200); color: var(--nuit); }
a.sidenav__link:hover > .icon { color: var(--foret-700); transform: translateX(2px); }

.sidenav__link.is-active { background: var(--foret-100); color: var(--foret-700); font-weight: 600; }
.sidenav__link.is-active > .icon { color: var(--foret-700); }
/* The marker grows out of the pill rather than appearing: at 150 ms it reads as the page
   arriving, and it is the one thing that moves when nothing is being hovered. */
.sidenav__link::before {
  content: ""; position: absolute; left: calc(-1 * var(--sp-2)); top: 50%;
  width: 3px; height: 0; border-radius: 0 3px 3px 0;
  background: var(--foret-700); transform: translateY(-50%);
  transition: height var(--duration);
}
.sidenav__link.is-active::before { height: 60%; }

.sidenav__link.is-unavailable { color: var(--beton-500); cursor: default; }
.sidenav__link.is-unavailable > .icon { opacity: 0.6; }

.scrim { position: fixed; inset: 0; z-index: var(--z-drawer); background: var(--scrim); }
.sidenav { z-index: calc(var(--z-drawer) + 1); }

/* On a phone the drawer slides in over the page; its four groups follow, a step apart, so the
   eye lands on « Préparation » first instead of on twenty links at once. --i is set per group in
   base_app.html. prefers-reduced-motion switches every animation off in tokens.css. */
@keyframes sidenav-group-in {
  from { opacity: 0; transform: translateX(-8px); }
  to   { opacity: 1; transform: none; }
}
.sidenav.is-open .sidenav__group {
  animation: sidenav-group-in var(--duration) ease-out backwards;
  animation-delay: calc(var(--i, 0) * var(--duration) / 2);
}

.app-main { padding-block: var(--sp-6) var(--sp-12); }
.app-main:focus { outline: none; }

.topbar__brand .wordmark__by { display: none; }

@media (min-width: 600px) {
  .topbar__user { display: inline; }
  .topbar__brand .wordmark__by { display: inline; }
}

/* Desktop: the nav is a fixed full-height column; the top bar starts after it.
   Selectors are doubled to win over .btn (components.css loads later). */
@media (min-width: 1024px) {
  .topbar { margin-left: var(--nav-width); padding-inline: var(--sp-6); }
  .topbar .topbar__menu, .topbar .topbar__brand, .sidenav .sidenav__head .btn, .app-shell .scrim { display: none; }
  .sidenav { transform: none; visibility: visible; z-index: var(--z-nav); }
  /* The desktop nav is always there, so it never animates in. */
  .sidenav .sidenav__group { animation: none; opacity: 1; }
  .sidenav__head { min-height: var(--topbar-height); margin: calc(-1 * var(--sp-4)) 0 var(--sp-4); padding-inline: var(--sp-3); border-bottom: var(--hairline); }
  .app-main { margin-left: var(--nav-width); }
}

/* ------------------------------------------------------------------------- */
/* Field shell: phone first, bottom action bar                                */
/* ------------------------------------------------------------------------- */

.field-topbar {
  position: sticky; top: 0; z-index: var(--z-topbar);
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: var(--topbar-height); padding: var(--sp-2) var(--sp-4);
  background: var(--surface); border-bottom: var(--hairline);
}
.field-topbar__title { flex: 1; min-width: 0; }
.field-topbar__title h1 { font-size: var(--fs-h2); line-height: var(--lh-h2); }
.field-topbar__project { font-size: var(--fs-micro); line-height: var(--lh-micro); color: var(--beton-500); }
.field-main {
  max-width: 40rem; margin-inline: auto;
  padding: var(--sp-4) var(--sp-4) calc(var(--actionbar-height) + var(--sp-6));
}
.field-main:focus { outline: none; }
.actionbar {
  position: fixed; inset-inline: 0; bottom: 0; z-index: var(--z-topbar);
  display: flex; gap: var(--sp-3); align-items: center;
  min-height: var(--actionbar-height); padding: var(--sp-3) var(--sp-4);
  background: var(--surface); border-top: var(--hairline);
}
.actionbar > .btn { flex: 1; min-height: var(--touch-min); }

/* ------------------------------------------------------------------------- */
/* Public shell: a thin bar, the page, a footer                               */
/* ------------------------------------------------------------------------- */

.public { min-height: 100vh; display: flex; flex-direction: column; background: var(--sable); }

.public__bar {
  position: sticky; top: 0; z-index: var(--z-topbar);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  min-height: var(--topbar-height); padding: var(--sp-2) var(--sp-4);
  background: var(--surface); border-bottom: var(--hairline);
}
.public__home { display: inline-flex; align-items: center; text-decoration: none; }
.public__nav { display: flex; align-items: center; gap: var(--sp-2); }
.public__nav > a:not(.btn) { padding: var(--sp-2); color: var(--foret-700); white-space: nowrap; }
.public__bar .public__nav > a:not(.btn) { display: none; }   /* shown from 600px; always in the footer */

.public__main { flex: 1; }
.public__main--padded {
  width: 100%; max-width: var(--content-max); margin-inline: auto;
  padding: var(--sp-8) var(--sp-4);
}
.public__main:focus { outline: none; }

.public__footer { background: var(--surface); border-top: var(--hairline); }
.public__footer-inner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--sp-4); max-width: var(--content-max); margin-inline: auto;
  padding: var(--sp-6) var(--sp-4);
}

@media (min-width: 600px) {
  .public__bar { padding-inline: var(--sp-6); }
  .public__bar .public__nav > a:not(.btn) { display: inline; }
  .public__footer-inner { padding-inline: var(--sp-6); }
  .public__main--padded { padding-inline: var(--sp-6); }
}

/* Account pages (connexion, inscription, mot de passe oublié, invitation): the site under the
   forest veil on the left with the brand over it, the form on the right. Below 900 px the panel
   becomes a band above the card and the drawing steps aside — it has no room there, and the
   words were being read through it. */
.auth { min-height: 100vh; display: grid; grid-template-rows: auto 1fr; background: var(--sable); }
.auth__brand {
  position: relative; display: grid; grid-template-rows: auto 1fr;
  background: var(--foret-800); color: var(--sur-foret); overflow: hidden;
}
.auth__wordmark {
  position: relative; z-index: 1; justify-self: start;
  padding: var(--sp-6) var(--sp-4) 0; text-decoration: none;
}
/* .photo sets position:relative and a ratio box; here the panel sets the size, so the two class
   names are needed to win over components.css, which is loaded after this file. */
.photo.auth__photo { position: absolute; inset: 0; border-radius: 0; }
.photo.auth__photo::before { display: none; }
.auth__brand .photo__attente > .illustration { display: none; }
.auth__brand .wordmark, .auth__brand .wordmark__by, .auth__brand .wordmark__name { color: var(--sur-foret); }
.auth__brand .auth__tagline, .auth__brand .auth__pitch { text-shadow: var(--ombre-texte); }
.auth__brand-text {
  position: relative; z-index: 1; align-self: center;
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4) var(--sp-6);
}
.auth__tagline { font: 600 var(--fs-h2)/var(--lh-h2) var(--font-display); max-width: 22ch; }
.auth__pitch { font-size: var(--fs-small); line-height: var(--lh-small); max-width: 46ch; }

.auth__main { display: grid; place-items: center; padding: var(--sp-8) var(--sp-4); }
.auth__main:focus { outline: none; }
.auth__card {
  width: 100%; max-width: 26rem; display: flex; flex-direction: column; gap: var(--sp-4);
  padding: var(--sp-6); background: var(--surface);
  border: var(--hairline); border-radius: var(--r-card); box-shadow: var(--ombre-carte);
}
.auth__card h1 { font-size: var(--fs-h2); line-height: var(--lh-h2); }
.auth__card > p { font-size: var(--fs-small); line-height: var(--lh-small); }
.auth__form { display: flex; flex-direction: column; gap: var(--sp-4); }
.auth__form .btn { margin-top: var(--sp-2); min-height: var(--touch-min); }

/* On an account page every field is one the person fills in, so the yellow edge would mark a
   difference that does not exist — and the charter keeps colour for meaning, never decoration. */
.auth .field { border-left: var(--field-border); }
.auth .field:focus { background: var(--surface); }
.auth .form-field.is-invalid .field { border-color: var(--alert); border-left: 1px solid var(--alert); }

@media (min-width: 900px) {
  .auth { grid-template-rows: none; grid-template-columns: 1fr 1fr; }
  .auth__wordmark { padding: var(--sp-8) var(--sp-8) 0; }
  .auth__brand-text { padding: var(--sp-4) var(--sp-8) var(--sp-12); gap: var(--sp-4); }
  .auth__tagline { font-size: var(--fs-h1); line-height: var(--lh-h1); }
  .auth__brand .photo__attente > .illustration { display: block; height: 50%; }
  .auth__main { padding: var(--sp-12) var(--sp-8); }
}

.cluster--tight { gap: var(--sp-2); flex-wrap: nowrap; }
.auth__intro { font-size: var(--fs-small); line-height: var(--lh-small); color: var(--beton-700); }
