  /* ============================================================
     ЗАПРЕЩЕНО ПОДЧЁРКИВАНИЕ ТЕКСТА - нигде, никогда, ни при каких
     состояниях. НЕ ОСЛАБЛЯТЬ, НЕ ОБХОДИТЬ, НЕ УДАЛЯТЬ.

     Почему так развёрнуто:
     * text-decoration НЕ наследуется, а РАСПРОСТРАНЯЕТСЯ на содержимое,
       и потомок не может её снять своим none. Поэтому none ставится
       ВСЕМ элементам - тогда её просто некому задать.
     * задаём и сокращённое свойство, и text-decoration-line: если где-то
       выставлено только line, шорткат мог бы не перекрыть его порядком.
     * -webkit-text-decoration нужен старым Safari, который не понимает
       отдельных подсвойств.
     * u, ins, abbr[title], s, del подчёркивает сам браузер, вне наших
       стилей, - перечислены явно.
     ============================================================ */
  *, *::before, *::after, *::first-line, *::marker,
  a, a:link, a:visited, a:hover, a:focus, a:focus-visible, a:active,
  u, ins, abbr, abbr[title], s, del, button, summary, label, legend {
    text-decoration: none !important;
    text-decoration-line: none !important;
    -webkit-text-decoration: none !important;
    text-underline-offset: 0 !important;
  }
  /* abbr[title] в некоторых браузерах подчёркивается точечной рамкой, а не
     декорацией текста - она снимается отдельно. */
  abbr, abbr[title] { border-bottom: 0 !important; }

  * { box-sizing: border-box; }
  html { color-scheme: light; scroll-behavior: smooth; }
  @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
  body {
    margin: 0;
    min-height: 100vh;
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: #12141A;
    -webkit-font-smoothing: antialiased;
  }


  a { color: inherit; }
  a:focus-visible, button:focus-visible { outline: 2px solid #12141A; outline-offset: 3px; }

  .wrap { max-width: 1180px; margin: 0 auto; padding: 0 24px; }


  /* Плашка и фон страницы тоже описаны в /app/static/css/header.css - один
   раз на сайт и на кабинет; здешние копии успели разойтись со своими
   двойниками (скругление 28px против 24px). */

/* Шапка (логотип, меню, плашка активного пункта, переключатель языка,
     кружок учётной записи, выпадающие меню) живёт в одном файле на весь
     проект: /app/static/css/header.css. И сайт, и кабинет подключают его же -
     разметка, стили и поведение шапки существуют в единственном экземпляре. */

  .modal-overlay[hidden] { display: none; }
  .modal {
    position: relative;
    width: 100%;
    max-width: 420px;
    max-height: calc(100vh - 48px);
    overflow-y: auto;
    padding: 32px 30px;
    background: rgba(255,255,255,0.86);
  }
  .modal-close {
    position: absolute;
    top: 18px;
    right: 18px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: rgba(18,20,26,0.07);
    border-radius: 50%;
    cursor: pointer;
    color: #12141A;
  }
  .modal-close:hover { background: rgba(18,20,26,0.14); }
  .mode-tabs {
    position: relative;
    display: flex;
    background: rgba(18,20,26,0.06);
    border-radius: 999px;
    padding: 4px;
    margin: 4px 0 24px;
  }
  .mode-tabs .lang-thumb {
    width: calc(50% - 4px);
    top: 4px;
    left: 4px;
    height: calc(100% - 8px);
  }
  .mode-tab {
    position: relative;
    z-index: 2;
    flex: 1;
    border: none;
    background: transparent;
    font: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    padding: 9px 10px;
    border-radius: 999px;
    color: #12141A;
    opacity: 0.5;
    cursor: pointer;
    transition: color 0.3s ease, opacity 0.3s ease;
  }
  .mode-tab.active { color: #fff; opacity: 1; }
  .login-panel h3 {
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 8px;
  }
  .login-note {
    font-size: 0.85rem;
    line-height: 1.5;
    color: #34384A;
    margin: 0 0 18px;
  }
  .login-note:empty { display: none; margin: 0; }
  .login-form { display: flex; flex-direction: column; }
  .login-form > label { margin-bottom: 14px; }
  .login-form label {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 0.78rem;
    font-weight: 700;
    color: #3E4258;
  }
  .login-form[hidden] { display: none; }
  .register-fields {
    display: flex;
    flex-direction: column;
    gap: 14px;
    height: 0;
    margin-bottom: 0;
    overflow: hidden;
  }
  @media (prefers-reduced-motion: reduce) {
    .register-fields { transition: none !important; }
  }

  /* Method / instrument detail pages */
  .detail-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    font-weight: 600;
    color: #3E4258;
    text-decoration: none;
    opacity: 0.75;
    margin-bottom: 20px;
  }
  .detail-back:hover { opacity: 1; }

  .detail-card {
    max-width: 720px;
    margin: 0 auto 56px;
    padding: 32px 32px 40px;
  }
  .detail-card .art { margin-bottom: 26px; }
  .detail-card .art canvas { width: 100%; height: auto; }
  .detail-card h1 {
    font-size: clamp(1.6rem, 3vw, 2.1rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 6px;
  }
  .detail-card .lead {
    font-size: 0.88rem;
    font-weight: 600;
    color: #5B5FE0;
    margin-bottom: 16px;
  }
  .detail-card > p.detail-body {
    font-size: 1rem;
    line-height: 1.6;
    color: #34384A;
    margin: 0 0 28px;
  }
  .detail-subhead {
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: #3E4258;
    margin: 0 0 12px;
  }
  .detail-card .gear { margin-top: 0; margin-bottom: 28px; }
  .gear a.gear-link {
    font-size: 0.78rem;
    font-weight: 600;
    background: rgba(18,20,26,0.06);
    padding: 6px 13px;
    border-radius: 999px;
    color: #3E4258;
    text-decoration: none;
    transition: background 0.2s ease, color 0.2s ease;
  }
  .gear a.gear-link:hover { background: #12141A; color: #fff; }

  .detail-used-for {
    font-size: 0.95rem;
    color: #34384A;
    margin: 0 0 22px;
  }
  .detail-used-for a { font-weight: 700; }

  .specs-placeholder {
    font-size: 0.86rem;
    font-style: italic;
    color: #5A5E70;
    margin: 0 0 28px;
  }

  /* Заголовок метода стоит первым узлом страницы, сам по себе - без плашки,
     без картинки и без ссылки возврата, которые были тут раньше. Размеры
     унаследованы от .detail-card h1, чтобы смена обрамления не поменяла
     заодно и типографику. */
  .detail-title {
    font-size: clamp(1.7rem, 3.2vw, 2.3rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 28px;
  }

  /* Иллюстрация блока, загружаемая в админке. Ограничена по высоте: снимки
     и схемы приходят в произвольных пропорциях, и без потолка вертикальная
     картинка заняла бы весь экран. */
  .block-image {
    display: block;
    max-width: 100%;
    max-height: 360px;
    margin: 18px 0 0;
    border-radius: 18px;
    object-fit: contain;
  }

  /* Заголовок секции на странице метода (сейчас - "Instruments" над
     плитками приборов). Кегль между заголовком страницы и заголовком внутри
     плашки: секция это уровень ниже названия метода, но выше блока. */
  .detail-section-title {
    font-size: 1.35rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 8px 0 18px;
    scroll-margin-top: 96px;
  }

  /* Плитки приборов - вместо прежней общей плашки "Instruments used" со
     списком текстовых ссылок. Каждая плитка это самостоятельная .plaque,
     поэтому фон/скругление/тень достаются даром. auto-fill, а не fixed
     columns: у метода бывает и один прибор, и три. */
  .instrument-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 24px;
    margin-bottom: 56px;
    scroll-margin-top: 96px;
  }
  .instrument-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    padding: 24px 20px 20px;
    text-decoration: none;
    color: inherit;
    transition: transform 0.18s ease, box-shadow 0.18s ease;
  }
  .instrument-tile:hover { transform: translateY(-3px); }
  /* Фиксированная высота фото-области, а не самой картинки: приборы сняты в
     разных пропорциях, и без общей рамки названия под ними разъехались бы по
     вертикали. contain, чтобы ничего не обрезалось. */
  .instrument-tile-photo {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 150px;
  }
  .instrument-tile-photo img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
  }
  .instrument-tile-nophoto {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 84px;
    height: 84px;
    border-radius: 50%;
    background: #E8EAF2;
    color: #5B5FE0;
    font-size: 2rem;
    font-weight: 800;
  }
  .instrument-tile-name {
    font-size: 1rem;
    font-weight: 700;
    text-align: center;
    color: #12141A;
  }

  .method-section { padding: 34px 44px; margin-bottom: 24px; }
  .method-section:last-child { margin-bottom: 56px; }
  /* Компенсация залипшей шапки при переходе по якорю из меню. */
  .method-section { scroll-margin-top: 96px; }

  /* Фотография прибора на его собственной странице - в такой же плашке, что и
     блоки, но по центру и с потолком по высоте: снимки приборов сняты в очень
     разных пропорциях, вертикальный без ограничения занял бы весь экран. */
  .instrument-hero {
    display: flex;
    justify-content: center;
  }
  .instrument-hero img {
    max-width: 100%;
    max-height: 340px;
    object-fit: contain;
  }
  .method-section-heading {
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 14px;
  }
  .method-section p {
    font-size: 0.96rem;
    line-height: 1.68;
    color: #34384A;
    margin: 0;
    max-width: 760px;
  }
  .app-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 16px;
    max-width: 760px;
  }
  .app-list li {
    font-size: 0.94rem;
    line-height: 1.62;
    color: #34384A;
  }
  .app-list li strong { color: #12141A; }
  .method-section .gear { margin: 0; }

  /* Split blocks carry their own media column flush against the card's
     edges - so the shared .method-section padding is disabled here and
     re-applied only to the text column (skipping its inner edge, where
     the flex `gap` already provides spacing from the media column).
     Text comes first in the DOM/on the left, media (animation) second/
     on the right - so it's media's RIGHT-side corners that touch the
     card and need rounding, and text's LEFT side that touches the card. */
  /* The disk-mask (JS-computed --disk-mask) must cut a hole only in the
     card's own background, never in its content (the iframe/text sitting
     on top) - so .plaque's background/blur/border/shadow move to a
     ::before behind the content, and the mask targets that alone. */
  .method-section-split {
    position: relative;
    display: flex;
    gap: 32px;
    align-items: stretch;
    padding: 0;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: none;
    box-shadow: none;
  }
  .method-section-split::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    background: rgba(255, 255, 255, 0.62);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    border: 1px solid rgba(255, 255, 255, 0.55);
    box-shadow: 0 1px 1px rgba(18,20,26,0.04), 0 20px 40px -20px rgba(18,20,26,0.25);
    mask-image: var(--disk-mask, none);
    -webkit-mask-image: var(--disk-mask, none);
    pointer-events: none;
  }
  .method-section-split .method-section-text,
  .method-section-split .method-section-media {
    position: relative;
    z-index: 1;
  }
  .method-section-media { flex: 0 0 380px; }
  .method-anim-frame {
    width: 100%;
    height: 100%;
    border: none;
    display: block;
    background: transparent;
    border-radius: 0 28px 28px 0;
  }
  .method-section-split .method-section-text { flex: 1; min-width: 0; padding: 34px 0 34px 44px; }
  /* Absolutely positioned, not width/height:100% - a canvas whose own CSS
     size is 100% of a flex-stretched parent while a script also resizes
     that same canvas's raster (width/height attributes) every frame is a
     feedback loop waiting to happen: any single frame where the percentage
     briefly resolves against the canvas's own intrinsic size instead of the
     parent's is enough to start it doubling forever (measured: one bad
     redeploy sent it to 25000px in well under a second). Absolute + inset
     makes the canvas's box geometrically incapable of feeding back into its
     own containing block's size, full stop - the 34px top/bottom inset
     matches .method-section-text's own vertical padding so the drawn chart
     lines up with the paragraph's actual first/last line instead of the
     stretched (padding-included) box edge.

     height/width are explicit (calc()/100%), never "auto" - a replaced
     element (canvas, like img/video) with an auto-computed dimension does
     NOT solve it from opposite insets the way a normal box would; it falls
     back to its own intrinsic size (the width/height HTML attributes)
     regardless of top+bottom being set. That silently un-did the whole
     point of this rule (measured: computed height stuck at the canvas's
     raw attribute default no matter what the layout around it did) until
     both dimensions got real values instead of being left for insets to
     imply. */
  .thermogram-canvas {
    position: absolute;
    top: 34px;
    left: 0;
    width: 100%;
    height: calc(100% - 68px);
    display: block;
    border-radius: 0 28px 28px 0;
  }
  @media (max-width: 760px) {
    .method-section-split { flex-direction: column; }
    .method-section-media { flex: none; width: 100%; }
    .method-anim-frame { min-height: 320px; border-radius: 0 0 28px 28px; }
    /* Text and media stack instead of sitting side by side here, so there's
       nothing to vertically line the chart up WITH any more - fall back to
       filling the panel edge-to-edge like the iframe cards do, with its own
       explicit min-height (the canvas is out of flow via position:absolute,
       so it can't give its own parent a height the way an in-flow iframe
       does - the parent needs one set directly). */
    .method-section-thermogram .method-section-media { min-height: 320px; }
    .thermogram-canvas { top: 0; height: 100%; border-radius: 0 0 28px 28px; }
    .method-section-split .method-section-text { padding: 34px 44px 24px; }
  }
