lism.config.js でのカスタマイズ
プロジェクトのルートディレクトリ直下に lism.config.js(または lism.config.mjs)を用意することで、スタイルではなくコンポーネントの挙動をカスタマイズすることができます。
Vite / Astro プラグインの登録(必須)
lism.config.js を読み込ませるには、Vite(または Astro)の設定ファイルでプラグインを登録する必要があります。登録していない場合、ファイルを置いてもデフォルト設定のままになります。
@lism-css/plugin が提供する統合プラグインを使います。これ1つで、設定の読み込み(JS ランタイムが lism.config.js を読む)・動的CSSビルド(dev/build で CSS に自動反映)・型自動生成(lism-env.d.ts) がまとめて有効になります。
pnpm add -D @lism-css/pluginimport { defineConfig } from 'astro/config';import { lismCss } from '@lism-css/plugin/astro';
export default defineConfig({ integrations: [lismCss()],});Next.js では Vite / Astro プラグインの代わりに、@lism-css/plugin/next の withLism() を使います。セットアップ手順はインストールの「Next.js での導入」を参照してください。
プラグインはプロジェクトルートから lism.config.js → lism.config.mjs の順で自動検出します。別の場所のファイルを使う場合は configPath オプションでパスを指定できます。
integrations: [lismCss({ configPath: './config/lism.config.js' })],フォーマット
export default { props: { hoge: { ... }, foo: { ... }, ... }, tokens: { hoge: { ... }, foo: { ... }, ... }, traits: { isHoge: 'is--hoge', setFoo: 'set--foo', ... },};/**
* isVar: 1 → クラス出力はせずstyle属性での変数出力のみ (--bdw, --keycolor など)
* bp: 0(= bp 省略時のデフォルト)→ Prop-valユーティリティクラス化されなければ、style属性で出力するだけ。
* bp: 1 → .-prop と --prop の セットがベースにあり、.-prop_bp と .--prop_bp で ブレイクポイント指定できる。
* .-prop{property:var(--prop)} が基本で、ユーティリティクラスは .-prop:val{property:value} となる。
*
* ↓コンポーネント処理で使用される
* tokenClass: 1 → 対応するトークン値がそのまま全てユーティリティクラス化されるもの。
* shorthands: → コンポーネント側で短く書くための設定
*
* ↓SCSS出力で使用される
* alwaysVar: 1 → state変数扱い。 .-prop,[class*=-prop:] {property:var(--prop)} の base 出力となり、
* ユーティリティクラスは --prop をセットする形になる。
* 加えて BPクラスも .-prop_$bp { property: var(--prop); --prop: var(--prop_$bp) !important; } を出力し、
* 常に --prop が当該要素の現在値になるよう上書きされる(consumer が --prop を参照できる)。
* important: 1 → !important を付けて最終的に出力する
*/
const PLACE_PRESETS = ['start', 'center', 'end'] as const;
const PLACE_FX_PRESETS = ['flex-start', 'flex-end'] as const;
const PLACE_SHORTHANDS = { s: 'start', e: 'end', c: 'center', fs: 'flex-start', fe: 'flex-end' } as const;
export default {
f: { prop: 'font', presets: ['inherit'] },
fz: { prop: 'fontSize', token: 'fz', tokenClass: 1, bp: 1 },
fw: {
prop: 'fontWeight',
token: 'fw',
tokenClass: 1,
presets: ['100', '200', '300', '400', '500', '600', '700', '800', '900'],
},
ff: { prop: 'fontFamily', token: 'ff', tokenClass: 1 },
fs: { prop: 'fontStyle', presets: ['italic'], shorthands: { i: 'italic' } },
lh: {
prop: '--hl',
isVar: 1,
token: 'hl',
tokenClass: 1,
utils: { '1': '0px' },
},
hl: {
prop: '--hl',
isVar: 1,
token: 'hl',
tokenClass: 1,
bp: 1,
// hl="0" で half-leading なし (--hl:0px) を表現できるようにする互換ユーティリティ。
// lh="1"(互換ショートカット)の .-lh:1 と同じ出力にし、正規 prop の hl 側でも揃えられるようにする。
utils: { '0': '0px' },
},
lts: { prop: 'letterSpacing', token: 'lts', tokenClass: 1 },
ta: { prop: 'textAlign', presets: ['center', 'left', 'right'] },
td: { prop: 'textDecoration', utils: { none: 'none' } },
tt: { prop: 'textTransform', utils: { upper: 'uppercase', lower: 'lowercase' } },
// te: { prop: 'textEmphasis', presets: ['filled'] },
// tsh: { prop: 'textShadow' },
d: {
prop: 'display',
presets: ['none', 'block', 'flex', 'inline-flex', 'grid', 'inline-grid', 'inline', 'inline-block'],
bp: 1,
},
o: { prop: 'opacity', presets: ['0'], token: 'o', tokenClass: 1 },
v: { prop: 'visibility', presets: ['hidden'] },
ov: { prop: 'overflow', presets: ['hidden', 'auto', 'clip'] },
'ov-x': { prop: 'overflowX', presets: ['clip', 'auto', 'scroll'] },
'ov-y': { prop: 'overflowY', presets: ['clip', 'auto', 'scroll'] },
// overflow-clip-margin → safariで使えない
ar: {
prop: 'aspectRatio',
presets: ['21/9', '16/9', '3/2', '1/1'], // 4/3, 2/1
token: 'ar',
tokenClass: 1,
bp: 1,
},
// size
w: { prop: 'width', utils: { fit: 'fit-content' }, presets: ['100%'], token: 'sz', bp: 1 },
h: { prop: 'height', utils: { fit: 'fit-content' }, presets: ['100%'], token: 'sz', bp: 1 },
'min-w': { prop: 'minWidth', presets: ['100%'], token: 'sz', bp: 1 },
'max-w': { prop: 'maxWidth', presets: ['100%'], token: 'sz', bp: 1 },
'min-h': { prop: 'minHeight', presets: ['100%'], token: 'sz', bp: 1 },
'max-h': { prop: 'maxHeight', presets: ['100%'], token: 'sz', bp: 1 },
contentSize: { isVar: 1, presets: ['s', 'm', 'l', 'xl'], token: 'sz' },
sz: { prop: 'inlineSize', token: 'sz' },
'min-sz': { prop: 'minInlineSize', token: 'sz' },
'max-sz': {
prop: 'maxInlineSize',
token: 'sz',
tokenClass: 1,
presets: ['full', 'bleed'],
exUtility: {
full: '',
bleed: '',
},
},
bsz: { prop: 'blockSize', token: 'sz' },
'min-bsz': { prop: 'minBlockSize', token: 'sz' },
'max-bsz': { prop: 'maxBlockSize', token: 'sz' },
// bg
bg: { prop: 'background' },
bgi: { prop: 'backgroundImage' },
bgr: { prop: 'backgroundRepeat', presets: ['no-repeat'] },
bgp: { prop: 'backgroundPosition', presets: ['center'] },
bgsz: { prop: 'backgroundSize', presets: ['cover', 'contain'] },
// bga: { prop: 'backgroundAttachment' }, // fixed
// bgo: { prop: 'backgroundOrigin' }, // border, padding, content
// bgblend: { prop: 'backgroundBlendMode' },
// bgclip: {
// prop: 'backgroundClip',
// presets: ['text'],
// },
bgc: {
prop: 'backgroundColor',
presets: ['base', 'base-2', 'text', 'brand', 'accent', 'inherit', 'transparent'],
token: 'color',
exUtility: { inherit: { 'background-color': 'inherit' } },
alwaysVar: 1,
},
c: {
// Note: bg系(bgclip)より後にくるように。
prop: 'color',
presets: ['base', 'text', 'text-2', 'brand', 'accent', 'inherit'],
token: 'color',
exUtility: {
inherit: { color: 'inherit' }, // --c ではなく color で出力したい
// mix: {'--_c1:currentColor;--_c2:transparent;--c:color-mix(in srgb, var(--_c1) var(--_mix-c, 50%), var(--_c2))'},
},
alwaysVar: 1,
},
keycolor: { isVar: 1, token: 'color' },
bd: { prop: 'border', presets: ['none'] },
bds: { isVar: 1, presets: ['dashed', 'dotted', 'double'] },
bdc: {
isVar: 1,
presets: ['brand', 'accent', 'divider', 'inherit', 'transparent'],
utils: { current: 'currentColor' },
token: 'color',
},
bdw: { isVar: 1, bp: 1 }, // --bdw のみ
'bd-x': { prop: 'borderInline' },
'bd-y': { prop: 'borderBlock' },
'bd-s': { prop: 'borderInlineStart' },
'bd-e': { prop: 'borderInlineEnd' },
'bd-bs': { prop: 'borderBlockStart' },
'bd-be': { prop: 'borderBlockEnd' },
'bd-t': { prop: 'borderTop' },
'bd-b': { prop: 'borderBottom' },
'bd-l': { prop: 'borderLeft' },
'bd-r': { prop: 'borderRight' },
bdrs: {
prop: 'borderRadius',
presets: ['0'],
token: 'bdrs',
tokenClass: 1,
bp: 1,
alwaysVar: 1,
},
'bdrs-tl': { prop: 'borderTopLeftRadius', token: 'bdrs' },
'bdrs-tr': { prop: 'borderTopRightRadius', token: 'bdrs' },
'bdrs-br': { prop: 'borderBottomRightRadius', token: 'bdrs' },
'bdrs-bl': { prop: 'borderBottomLeftRadius', token: 'bdrs' },
'bdrs-ss': { prop: 'borderStartStartRadius', token: 'bdrs' },
'bdrs-se': { prop: 'borderStartEndRadius', token: 'bdrs' },
'bdrs-es': { prop: 'borderEndStartRadius', token: 'bdrs' },
'bdrs-ee': { prop: 'borderEndEndRadius', token: 'bdrs' },
bxsh: { prop: 'boxShadow', utils: { 0: 'none' }, token: 'bxsh', tokenClass: 1, bp: 1 },
// position
pos: {
prop: 'position',
presets: ['static', 'fixed', 'sticky', 'relative', 'absolute'],
bp: 1,
},
z: { prop: 'zIndex', presets: ['-1', '0', '1', '99'] },
t: { prop: 'top', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
l: { prop: 'left', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
r: { prop: 'right', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
b: { prop: 'bottom', utils: { 0: '0%' }, presets: ['50%', '100%'], token: 'space' },
i: { prop: 'inset', utils: { 0: '0%' }, token: 'space' },
'i-x': { prop: 'insetInline', token: 'space' },
'i-y': { prop: 'insetBlock', token: 'space' },
'i-s': { prop: 'insetInlineStart', token: 'space' },
'i-e': { prop: 'insetInlineEnd', token: 'space' },
'i-bs': { prop: 'insetBlockStart', token: 'space' },
'i-be': { prop: 'insetBlockEnd', token: 'space' },
// space
p: {
prop: 'padding',
presets: ['0'],
token: 'space',
tokenClass: 1,
alwaysVar: 1,
bp: 1,
},
px: { prop: 'paddingInline', presets: ['0'], token: 'space', tokenClass: 1, bp: 1 },
py: { prop: 'paddingBlock', presets: ['0'], token: 'space', tokenClass: 1, bp: 1 },
ps: { prop: 'paddingInlineStart', token: 'space', bp: 1 },
pe: { prop: 'paddingInlineEnd', token: 'space', bp: 1 },
pbs: { prop: 'paddingBlockStart', token: 'space', bp: 1 },
pbe: { prop: 'paddingBlockEnd', token: 'space', bp: 1 },
pl: { prop: 'paddingLeft', token: 'space' },
pr: { prop: 'paddingRight', token: 'space' },
pt: { prop: 'paddingTop', token: 'space' },
pb: { prop: 'paddingBottom', token: 'space' },
m: {
prop: 'margin',
presets: ['auto', '0'],
token: 'space',
tokenClass: 1,
alwaysVar: 1,
bp: 1,
},
mx: { prop: 'marginInline', presets: ['auto', '0'], token: 'space', tokenClass: 1, bp: 1 },
my: { prop: 'marginBlock', presets: ['auto', '0'], token: 'space', tokenClass: 1, bp: 1 },
ms: { prop: 'marginInlineStart', presets: ['auto'], token: 'space', bp: 1 },
me: { prop: 'marginInlineEnd', presets: ['auto'], token: 'space', bp: 1 },
mbs: { prop: 'marginBlockStart', token: 'space', bp: 1, presets: ['auto', '0'], tokenClass: 1 },
mbe: { prop: 'marginBlockEnd', presets: ['auto'], token: 'space', bp: 1 },
ml: { prop: 'marginLeft', token: 'space' },
mr: { prop: 'marginRight', token: 'space' },
mt: { prop: 'marginTop', token: 'space' },
mb: { prop: 'marginBottom', token: 'space' },
g: {
prop: 'gap',
presets: ['0', 'inherit'],
exUtility: { inherit: { gap: 'inherit' } },
token: 'space',
tokenClass: 1,
bp: 1,
},
cg: { prop: 'columnGap', token: 'space' },
rg: { prop: 'rowGap', token: 'space' },
cols: { isVar: 1, bp: 1 },
rows: { isVar: 1, bp: 1 },
// flex
fxf: { prop: 'flexFlow' },
fxw: { prop: 'flexWrap', presets: ['wrap'], bp: 1 },
fxd: { prop: 'flexDirection', presets: ['column', 'column-reverse', 'row-reverse'], bp: 1 },
fx: { prop: 'flex', presets: ['1'], bp: 1 },
fxg: { prop: 'flexGrow', presets: ['1'] },
fxsh: { prop: 'flexShrink', presets: ['0'] },
fxb: { prop: 'flexBasis', bp: 1 },
// grid
// gd: { prop: 'grid' },
gt: {
prop: 'gridTemplate',
bp: 1,
},
gta: { prop: 'gridTemplateAreas', bp: 1 },
gtc: {
prop: 'gridTemplateColumns',
presets: ['subgrid'],
bp: 1,
},
gtr: {
prop: 'gridTemplateRows',
presets: ['subgrid'],
bp: 1,
},
gaf: { prop: 'gridAutoFlow', presets: ['row', 'column'], bp: 1 }, //dense
gac: { prop: 'gridAutoColumns' },
gar: { prop: 'gridAutoRows' },
// grid item
ga: { prop: 'gridArea', utils: { '1/1': '1 / 1' }, bp: 1 },
gc: { prop: 'gridColumn', utils: { '1/-1': '1 / -1' }, bp: 1 },
gr: { prop: 'gridRow', utils: { '1/-1': '1 / -1' }, bp: 1 },
gcs: { prop: 'gridColumnStart' },
gce: { prop: 'gridColumnEnd' },
grs: { prop: 'gridRowStart' },
gre: { prop: 'gridRowEnd' },
// places
// -(ai|ac|ji|jc|aslf|jslf): / -$1:
ai: {
prop: 'alignItems',
presets: [...PLACE_PRESETS, 'stretch', ...PLACE_FX_PRESETS],
shorthands: PLACE_SHORTHANDS,
bp: 1,
},
ac: {
prop: 'alignContent',
presets: [...PLACE_PRESETS, ...PLACE_FX_PRESETS],
utils: { between: 'space-between' },
shorthands: PLACE_SHORTHANDS,
bp: 1,
},
ji: {
prop: 'justifyItems',
presets: [...PLACE_PRESETS, 'stretch', ...PLACE_FX_PRESETS],
shorthands: PLACE_SHORTHANDS,
bp: 1,
},
jc: {
prop: 'justifyContent',
presets: [...PLACE_PRESETS, ...PLACE_FX_PRESETS],
utils: { between: 'space-between' },
shorthands: PLACE_SHORTHANDS,
bp: 1,
},
pi: { prop: 'placeItems', presets: PLACE_PRESETS },
pc: { prop: 'placeContent', presets: PLACE_PRESETS },
aslf: {
prop: 'alignSelf',
presets: [...PLACE_PRESETS, 'stretch'],
shorthands: PLACE_SHORTHANDS,
},
jslf: {
prop: 'justifySelf',
presets: [...PLACE_PRESETS, 'stretch'],
shorthands: PLACE_SHORTHANDS,
},
pslf: { prop: 'placeSelf', presets: PLACE_PRESETS },
order: { prop: 'order', presets: ['0', '-1', '1'], bp: 1 },
// transform
// translate: {
// prop: 'translate',
// utils: {
// '-50X': '-50% 0',
// '-50Y': '0 -50%',
// '-50XY': '-50% -50%',
// },
// },
// rotate: {
// prop: 'rotate',
// utils: {
// [`45`]: '45deg',
// '-45': '-45deg',
// [`90`]: '90deg',
// '-90': '-90deg',
// // '180': '180deg',
// },
// },
// scale: {
// prop: 'scale',
// utils: {
// '-X': '-1 1',
// '-Y': '1 -1',
// '-XY': '-1 -1',
// },
// },
// others
ovw: { prop: 'overflowWrap', presets: ['anywhere'] },
whs: { prop: 'whiteSpace', presets: ['nowrap'] },
// wordbreak: { prop: 'wordBreak', utils: { keep: 'keep-all', all: 'break-all' } },
float: { prop: 'float', presets: ['left', 'right'] },
clear: { prop: 'clear', presets: ['both'] },
iso: { prop: 'isolation', presets: ['isolate'] },
wm: { prop: 'writingMode', presets: ['vertical-rl'], bp: 1 },
} as const; カスタマイズ例
例えば次のような設定ファイルを用意するとします。
import DEFAULT_CONFIG from 'lism-css/default-config';const { props } = DEFAULT_CONFIG;
export default { props: { // 既存propにpresetsを追加 ta: { presets: [...(props.ta.presets || []), 'justify'] }, // 既存propにutility値を追加 p: { utils: { box: '2em' } }, // 新しいpropの追加(filterはデフォルトに含まれない) filter: { utils: { blur: 'blur(3px)' } }, }, tokens: { // トークンは { key: value } の値マップで定義(既定に deep-merge される) // → :root { --lts--2xl: .5em } の出力と -lts:2xl のユーティリティが自動生成される lts: { '2xl': '.5em' }, }, traits: { // Trait(is--* / has--*)出力用のプロパティを追加 isHoge: 'is--hoge', },};上記のカスタマイズによって、Lismコンポーネントでは次のような挙動が追加されます。
ta='justify'→-ta:justifyを出力する。p='box'→-p:boxを出力する。filter='blur'→-filter:blurを出力する。lts='2xl'→-lts:2xlを出力する。isHoge→is--hogeを出力する。
<Box p="box" ta="justify" filter="blur" lts="2xl" isHoge>Box</Box>
↓ 出力結果
<div class="l--box is--hoge -p:box -ta:justify -filter:blur -lts:2xl">Box</div>追加した prop / trait は型も自動解禁されます
統合プラグイン(型自動生成が有効)を使っている場合、lism.config.js で追加した prop / trait は lism-env.d.ts 経由で型側にも自動で解禁されます(CustomPropRegistry / CustomTraitRegistry の拡張として出力)。そのため上記の <Box filter="blur" ... isHoge> のような新規 prop / trait も、エディタや astro check で型エラーになりません。手書きの型拡張は不要です(lism-env.d.ts は git にコミットしてください)。
なお、既存 prop への値追加(ta="justify" など)はもともと任意の文字列を受け付けるため、型エラーにはなりません(補完候補には出ません)。
ただし、lism.config.js に props を追加しただけでは、コンポーネントのHTML出力が変わるだけで、対応するユーティリティクラスのスタイルは生成されません。スタイルを反映する方法(プラグインによる自動反映 / CLI / SCSS)は追加スタイルを読み込ませる方法を参照してください。
ブレイクポイント(xs / xl)の有効化
デフォルトのブレイクポイントは xs: 0(無効)/ sm: 480px / md: 800px / lg: 1120px / xl: 0(無効)です。値 0 は「無効=CSSクエリを出力しない」を表します。
xs や xl を有効化するには、lism.config.js の breakpoints に、有効化したいブレイクポイントのサイズだけを指定するのが最も簡単です。
export default { breakpoints: { xs: '360px', // xs を有効化 xl: '1400px', // xl を有効化 },};これだけで、ブレイクポイント対応(bp: 1)の全 Property Class が xs / xl のレスポンシブクラス(-p_xs / -p_xl など)も出力するようになります。prop ごとに個別指定する必要はありません。また、@lism-css/plugin の統合プラグインを使っている場合は dev/build の CSS に自動反映されます。
これにより、コンポーネント側でもオブジェクト記法で xs / xl を指定できるようになります。
<Box p={{ base: 20, xs: 10, sm: 30 }} />型・補完でも xs / xl を提示させるには、Responsive ページを参照してください。統合プラグイン(@lism-css/plugin)を使っている場合は、lism-env.d.ts が自動生成されるため手書き拡張は不要です。
full.css を読み込んでいる場合も、xs / xl はデフォルトでは無効です(出力されるのは sm / md / lg)。利用するには上記と同様に、breakpoints でサイズを指定して有効化してください。
xs / xl などを有効化すると bp: 1 の全 Property Class に該当ブレイクポイントのブロックが追加されるぶん、CSS サイズが増えます。CSS purge との併用が前提の設計です。purge を使わない場合は、bp のリスト形式(bp: ('sm', 'md') など)で prop ごとに出力ブレイクポイントを絞ることを検討してください。
SCSS を直接利用する構成では、$breakpoints の上書きによる有効化も利用できます(SCSS でのカスタマイズを参照)。
追加スタイルを読み込ませる方法
lism.config.js で props を増やしただけでは、対応するユーティリティクラスのスタイルは存在しません。次のいずれかでスタイルを追加してください。
Vite / Astro プラグイン使用時は自動反映される
@lism-css/plugin/vite / @lism-css/plugin/astro の統合プラグイン(各エントリの lismCss())を登録している場合、lism.config.js の props / tokens の追加・変更は dev サーバー・ビルドの両方で CSS に自動反映されます。手動での CLI ビルドは不要です。
dev サーバー起動中に lism.config.js を変更すると HMR で CSS が再生成されます。
軽微な追加なら手書きで済ませる
カスタムトークンが少数で済むなら、Lism Props の :value 記法と global.css への手書きで十分です。
@layer lism-base { :root { --lts--2xl: 0.15em; }}
/* Property Class は @layer を付けない */.-lts\:2xl { letter-spacing: var(--lts--2xl);}<Text lts=":2xl">...</Text>トークンを体系的に拡張したい場合のみ、後述の CLI / SCSS 経由に切り替えるとよいでしょう。
lism-css のCLIコマンドでCSSビルドする
Vite / Astro を使わない構成(純 SCSS 構成・他バンドラ等)で lism.config.js を CSS に反映させるには、@lism-css/plugin が提供する lism-css build を実行します。これは後方互換専用ではなく、そのような構成向けの現在も推奨される正式な方法です。
npx lism-css build今回の例だと、以下のスタイルがこのコマンドによって lism-css/main.css 内に自動で生成されます。
.-ta\:justify { text-align: justify;}.-p\:box { padding: 2em;}.-filter\:blur { filter: blur(3px);}.-lts\:2xl { letter-spacing: var(--lts--2xl);}tokens に値を書いておけば、.-lts\:2xl { letter-spacing: var(--lts--2xl) } のような トークン参照を含むユーティリティクラス に加えて、参照先の CSS 変数(:root { --lts--2xl: .5em } のような 値そのもの)も同時に生成されます。なお、値に '-' を指定したキーは「名前だけを登録し、実値は出力しない」指定です(:root 宣言を生成せず、実値は手書きSCSS側で定義します。主に color / palette で使います)。
一方で is-- クラスのスタイルは自動生成されないため、別途手動で定義して読み込ませる必要があります。
@layer lism-trait { .is--hoge { /* ... */ }}ビルド処理はパッケージを更新する度に再実行する必要があります。
パッケージのスタイルを再ビルドするコマンドのため、パッケージ更新ごとにビルドが必要です。
なお、full.css / full_no_layer.css はデフォルトでは再ビルドされません。full.css を使用している場合は、--full オプションを付けて実行してください。
npx lism-css build --fullSCSSファイルへの追加上書き
lism.config.js にあわせて、SCSS変数を上書きしてから読み込ませてもよいでしょう。SCSS 変数の詳細は SCSS でのカスタマイズ を参照してください。
// 設定カスタマイズ@use '../path-to/node_modules/lism-css/scss/setting' with ( $props: ( 'ta': ( utilities: ( 'justify': 'justify', ), ), 'p': ( utilities: ( 'box': '2em', ), ), 'filter': ( utilities: ( 'blur': 'blur(3px)', ), ), 'lts': ( utilities: ( '2xl': 'var(--lts--2xl)', ), ), ));
// lism の scssファイルを読み込む@use '../path-to/node_modules/lism-css/scss/main';
// トークン追記@layer lism-base { :root { --lts--2xl: 0.15em; }}